/// <summary>
        /// Encrypts the message data and put a result into the specified output stream.
        /// </summary>
        /// <param name="input">The stream containing the serialized message.</param>
        /// <param name="output">The result stream with the data being sent to the remote host.</param>
        public override void Encrypt(Stream input, GenuineChunkedStream output)
        {
#if DEBUG
            input.Position = 0;
#endif

            output.WriteByte(1);

            lock (this)
            {
                // write encrypted content
                if (this._encryptor != null)
                {
                    GenuineUtility.CopyStreamToStream(new CryptoStream(new FinishReadingStream(input), this._encryptor, CryptoStreamMode.Read), output);
                }
                else
                {
                    output.WriteStream(input);
                }

                if (this.KeyedHashAlgorithm != null)
                {
                    // and write down the calculated message hash
                    input.Position = 0;
                    output.WriteBuffer(this.KeyedHashAlgorithm.ComputeHash(input), -1);

                    // it's in the content, reset its position
                    if (this._encryptor == null)
                    {
                        input.Position = 0;
                    }
                }
            }
        }
        /// <summary>
        /// Processes incoming Security Session Establishing message and sent a response if it's available.
        /// </summary>
        /// <param name="ignored">Ignored.</param>
        private void Internal_InitiateEstablishingSecuritySession(object ignored)
        {
            try
            {
                // get the next packet
                if (this.IsEstablished)
                {
                    return;
                }

                GenuineChunkedStream outputStream = this.EstablishSession(Stream.Null, false);

                if (outputStream != null)
                {
                    this.SendMessage(outputStream);
                }
                return;
            }
            catch (Exception ex)
            {
                this.DispatchException(ex);

#if DEBUG
//				this.Remote.ITransportContext.IEventLogger.Log(LogMessageCategory.Security, null, "SecuritySession.Internal_InitiateEstablishingSecuritySession",
//					null, "Exception during establishing Security Session. Exception: {0}. Stack trace: {1}.", ex.Message, ex.StackTrace);
#endif

                this.Remote.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.SecuritySessionFailed, ex, this.Remote, this));
            }
        }
        /// <summary>
        /// Encrypts the message data and put a result into the specified output stream.
        /// </summary>
        /// <param name="input">The stream containing the serialized message.</param>
        /// <param name="output">The result stream with the data being sent to the remote host.</param>
        public override void Encrypt(Stream input, GenuineChunkedStream output)
        {
            // there are two good approaches here: either encrypt the stream directly into the target
            lock (this._encryptor)
                GenuineUtility.CopyStreamToStream(new CryptoStream(new FinishReadingStream(input), this._encryptor, CryptoStreamMode.Read), output);
            // or create separate encryptor instance for encrypting at run-time
//			stream.WriteStream(new ResettableCryptoStream(input, this.SymmetricAlgorithm.CreateEncryptor()));
        }
Beispiel #4
0
        /// <summary>
        /// Encrypts the message data and put a result into the specified output stream.
        /// </summary>
        /// <param name="input">The stream containing the serialized message.</param>
        /// <param name="output">The result stream with the data being sent to the remote host.</param>
        public override void Encrypt(Stream input, GenuineChunkedStream output)
        {
            // write session established flag
            output.WriteByte(1);

            // serialize messages into the output stream
            this.SspiSecurityContext.EncryptMessage(input, output, this.KeyProvider_SspiServer.RequiredFeatures);
        }
        /// <summary>
        /// Sends a message synchronously. Does not process exceptions!
        /// </summary>
        /// <param name="content">The content being sent to the remote host.</param>
        /// <param name="timeout">The sending must be completed before this moment.</param>
        public void LowLevel_SendSync(Stream content, int timeout)
        {
            // apply the connection-level security session
            if (this.ConnectionLevelSecurity != null)
            {
                GenuineChunkedStream outputStream = new GenuineChunkedStream(true);
                this.ConnectionLevelSecurity.Encrypt(content, outputStream);
                content = outputStream;
            }

            for ( ; ;)
            {
                if (!this.IsValid)
                {
                    throw GenuineExceptions.Get_Processing_TransportConnectionFailed();
                }
                if (!GenuineUtility.WaitOne(_namedEventRemoteReadCompleted.ManualResetEvent, GenuineUtility.GetMillisecondsLeft(timeout)))
                {
                    throw GenuineExceptions.Get_Send_Timeout();
                }
                if (this._closed != 0)
                {
                    throw GenuineExceptions.Get_Receive_ConnectionClosed();
                }
                this._namedEventRemoteReadCompleted.ManualResetEvent.Reset();

                // read the next portion
                int bytesRead = content.Read(this._sendBuffer, 0, this._sendSpaceSize);

                // LOG:
                BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0)
                {
                    binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "GenuineSaredMemoryConnection.LowLevel_SendSync",
                                                               LogMessageType.LowLevelTransport_AsyncSendingInitiating, null, null, this.Remote,
                                                               binaryLogWriter[LogCategory.LowLevelTransport] > 1 ? new MemoryStream(this._sendBuffer, 0, bytesRead) : null,
                                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                               this.DbgConnectionId, bytesRead,
                                                               null, null, null,
                                                               "Content sending.");
                }

                Marshal.Copy(this._sendBuffer, 0,
                             (IntPtr)(this._pointer.ToInt32() + this._sendOffset + SHARE_CONTENT_OFFSET),
                             bytesRead);
                this._MessageToSendTotalSize  = bytesRead;
                this._MessageToSendFinishFlag = bytesRead < this._sendSpaceSize ? 1 : 0;

                this._namedEventWriteCompleted.ManualResetEvent.Set();

                if (bytesRead < this._sendSpaceSize)
                {
                    this.UpdateLastTimeAMessageWasSent();
                    return;
                }
            }
        }
        /// <summary>
        /// Creates and initializes GenuineChunkedStream with the header containing Processor's
        /// data and the security context name.
        /// </summary>
        /// <returns>Created and initialized GenuineChunkedStream.</returns>
        protected GenuineChunkedStream CreateOutputStream()
        {
            GenuineChunkedStream stream = new GenuineChunkedStream(false);

            // name of the coder
            BinaryWriter binaryWriter = new BinaryWriter(stream);

            binaryWriter.Write(this.Name);

            return(stream);
        }
        /// <summary>
        /// Sends the stream to the remote host.
        /// </summary>
        /// <param name="message">The message.</param>
        public void SendMessage(Message message)
        {
            int            availableConnectionEntry = 0;
            HttpWebRequest httpWebRequest           = null;

            try
            {
                // serialize the message
                GenuineChunkedStream stream = new GenuineChunkedStream(false);
                using (BufferKeeper bufferKeeper = new BufferKeeper(0))
                {
                    MessageCoder.FillInLabelledStream(message, null, null, stream, bufferKeeper.Buffer,
                                                      (int)this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]);
                }

                // add the header
                GenuineChunkedStream resultStream = new GenuineChunkedStream(false);
                BinaryWriter         binaryWriter = new BinaryWriter(resultStream);
                HttpMessageCoder.WriteRequestHeader(binaryWriter, MessageCoder.PROTOCOL_VERSION, GenuineConnectionType.Invocation, this.ITransportContext.BinaryHostIdentifier, HttpPacketType.Usual, message.MessageId, string.Empty, this.Remote.LocalHostUniqueIdentifier);
                if (stream.CanSeek)
                {
                    resultStream.WriteStream(stream);
                }
                else
                {
                    GenuineUtility.CopyStreamToStream(stream, resultStream);
                }

                // get a connection
                availableConnectionEntry = FindAvailableConnectionEntry();
                httpWebRequest           = this.InitializeRequest("__GC_INVC_" + availableConnectionEntry.ToString(), this._keepalive);

                this.InitiateSending(new ConnectionInfo(httpWebRequest, availableConnectionEntry, message), resultStream,
                                     this._httpAsynchronousRequestTimeout);
            }
            catch
            {
                try
                {
                    if (httpWebRequest != null)
                    {
                        httpWebRequest.Abort();
                    }
                }
                catch
                {
                }

                this.ReleaseConnectionEntry(availableConnectionEntry);

                throw;
            }
        }
        /// <summary>
        /// Creates and returns a stream containing decrypted data.
        /// </summary>
        /// <param name="input">A stream containing encrypted data.</param>
        /// <returns>A stream with decrypted data.</returns>
        public override Stream Decrypt(Stream input)
        {
            // check on view whether it's session's packet
            if (input.ReadByte() == 0)
            {
                // continue the Security Session establishing
                Stream outputStream = this.EstablishSession(input, false);

                if (outputStream != null)
                {
                    GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.SendMessage), outputStream, false);
                }
                return(null);
            }

            lock (this)
            {
                GenuineChunkedStream output = new GenuineChunkedStream(false);
                byte[] sign = null;

                int signSize = 0;
                if (this.KeyedHashAlgorithm != null)
                {
                    signSize = this.KeyedHashAlgorithm.HashSize / 8;
                }

                // decrypt the content and fetch the sign
                if (this._decryptor != null)
                {
                    CryptoStream cryptoStream = new CryptoStream(new FinishReadingStream(output), this._decryptor, CryptoStreamMode.Write);
                    sign = GenuineUtility.CopyStreamToStreamExceptSign(input, cryptoStream, signSize);
                    cryptoStream.FlushFinalBlock();
                }
                else
                {
                    sign = GenuineUtility.CopyStreamToStreamExceptSign(input, output, signSize);
                }

                // check the sign
                if (this.KeyedHashAlgorithm != null)
                {
                    if (!ZeroProofAuthorizationUtility.CompareBuffers(sign, this.KeyedHashAlgorithm.ComputeHash(output), sign.Length))
                    {
                        throw GenuineExceptions.Get_Security_WrongSignature();
                    }
                    output.Position = 0;
                }

                output.ReleaseOnReadMode = true;
                return(output);
            }
        }
        /// <summary>
        /// Creates and returns a stream containing decrypted data.
        /// </summary>
        /// <param name="input">A stream containing encrypted data.</param>
        /// <returns>A stream with decrypted data.</returns>
        public override Stream Decrypt(Stream input)
        {
            // the first approach
            lock (this._decryptor)
            {
                GenuineChunkedStream output = new GenuineChunkedStream(true);
                GenuineUtility.CopyStreamToStream(new CryptoStream(new FinishReadingStream(input), this._decryptor, CryptoStreamMode.Read), output);
                return(output);
            }

            // the second approach
//			return new CryptoStream(new FinishReadingStream(input), this.SymmetricAlgorithm.CreateDecryptor(), CryptoStreamMode.Read);
        }
Beispiel #10
0
        /// <summary>
        /// Encrypts the stream under current security conditions.
        /// </summary>
        /// <param name="messageStream">Data to be encrypted.</param>
        /// <param name="outputStream">Stream to write encrypted content to.</param>
        /// <param name="sspiFeatureFlags">Requested features.</param>
        public void EncryptMessage(Stream messageStream, GenuineChunkedStream outputStream, SspiFeatureFlags sspiFeatureFlags)
        {
            // get package sizes
            lock (_secPkgContext_SizesLock)
            {
                if (!_secPkgContext_SizesInitialized)
                {
                    SspiApi.QueryContextSizes(this._phContext, ref this._secPkgContext_Sizes);
                    _secPkgContext_SizesInitialized = true;
                }
            }

            byte[]       chunk        = null;
            int          position     = 0;
            BinaryWriter outputWriter = new BinaryWriter(outputStream);

            if ((sspiFeatureFlags & SspiFeatureFlags.Encryption) != 0)
            {
                // it'll write signature automatically as well as encrypt content
                SspiApi.EncryptMessage(this._phContext, messageStream, outputWriter, ref this._secPkgContext_Sizes);
            }
            else if ((sspiFeatureFlags & SspiFeatureFlags.Signing) != 0)
            {
                // remember position to write signature size later
                outputStream.WriteInt32AndRememberItsLocation(0, out chunk, out position);
                long currentLength = outputStream.Length;

                // anyway will have to read this into buffer
                byte[] contentBuffer = new byte[(int)messageStream.Length];
                GenuineUtility.ReadDataFromStream(messageStream, contentBuffer, 0, contentBuffer.Length);

                // write signature
                SspiApi.MakeSignature(this._phContext, contentBuffer, outputWriter, ref this._secPkgContext_Sizes);

                // update signature size
                MessageCoder.WriteInt32(chunk, position, (int)(outputStream.Length - currentLength));

                // write the content
                outputWriter.Write((int)contentBuffer.Length);
                outputWriter.Write(contentBuffer, 0, contentBuffer.Length);
            }
            else
            {
                // just copy the source content
                //outputWriter.Write( (int) messageStream.Length );
                GenuineUtility.CopyStreamToStream(messageStream, outputStream);
            }
        }
        /// <summary>
        /// Sends the content of the log to the remote host.
        /// </summary>
        /// <param name="stream">The stream containing a request or a response.</param>
        /// <param name="sender">The remote host that sent this request.</param>
        /// <returns>The response.</returns>
        public Stream HandleMessage(Stream stream, HostInformation sender)
        {
            if (_stopped)
            {
                return(Stream.Null);
            }

            int expectedSize = 640000;

            // copy to an intermediate stream
            GenuineChunkedStream intermediateStream = new GenuineChunkedStream(true);

            GenuineUtility.CopyStreamToStream(this._memoryWritingStream, intermediateStream, expectedSize);

            // and send it as one chunk
            return(intermediateStream);
        }
            /// <summary>
            /// Reads messages from the connection and processes them synchronously.
            /// </summary>
            public void ReceiveSynchronously()
            {
                try
                {
                    for ( ; ;)
                    {
                        if (!this.SharedMemoryConnection.IsValid)
                        {
                            return;
                        }

                        using (Stream stream = this.SharedMemoryConnection.LowLevel_ReadSync(GenuineUtility.GetTimeout(this.SharedMemoryConnection._closeAfterInactivity)))
                        {
                            // receive the message
                            GenuineChunkedStream theMessage = new GenuineChunkedStream(true);
                            GenuineUtility.CopyStreamToStream(stream, theMessage);

                            // a message was successfully received
                            this.SharedMemoryConnection.Renew();
                            if (theMessage.Length == 0)
                            {
                                // LOG:
                                BinaryLogWriter binaryLogWriter = this.SharedMemoryConnectionManager.ITransportContext.BinaryLogWriter;
                                if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0)
                                {
                                    binaryLogWriter.WriteEvent(LogCategory.Connection, "SharedMemoryConnectionManager.ReceiveSynchronously",
                                                               LogMessageType.ConnectionPingReceived, null, null, null, null,
                                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                               null, null, this.SharedMemoryConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                                               "A message with zero size is treated as ping.");
                                }

                                continue;
                            }

                            this.SharedMemoryConnectionManager.ITransportContext.IIncomingStreamHandler.HandleMessage(theMessage, this.SharedMemoryConnection.Remote, GenuineConnectionType.Persistent, null, this.SharedMemoryConnection.DbgConnectionId, false, null, this.SharedMemoryConnection.ConnectionLevelSecurity, null);
                            this.SharedMemoryConnection.Renew();
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.SharedMemoryConnectionManager.ConnectionFailed(ex, this.SharedMemoryConnection);
                }
            }
Beispiel #13
0
        /// <summary>
        /// Creates and returns a stream containing decrypted data.
        /// </summary>
        /// <param name="input">A stream containing encrypted data.</param>
        /// <returns>A stream with decrypted data.</returns>
        public override Stream Decrypt(Stream input)
        {
            // check on view whether it's session's packet
            if (input.ReadByte() == 0)
            {
                // continue the Security Session establishing
                Stream outputStream = this.EstablishSession(input, false);

                if (outputStream != null)
                {
                    GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.SendMessage), outputStream, false);
                }
                return(null);
            }

            if (this.RijndaelKey == null)
            {
                throw GenuineExceptions.Get_Security_ContextWasNotEstablished(this.Name);
            }

            lock (this.RijndaelKey)
            {
                if (this._decryptor == null)
                {
                    Rijndael rijndael = Rijndael.Create();
                    rijndael.Key  = this.RijndaelKey;
                    rijndael.Mode = CipherMode.ECB;

                    this._encryptor = rijndael.CreateEncryptor();
                    this._decryptor = rijndael.CreateDecryptor();
                }
            }

            lock (this._decryptor)
            {
                GenuineChunkedStream output = new GenuineChunkedStream(true);
                GenuineUtility.CopyStreamToStream(new CryptoStream(new FinishReadingStream(input), this._decryptor, CryptoStreamMode.Read), output);

                GenuineUtility.CopyStreamToStream(input, Stream.Null);
                input.Close();

                return(output);
            }
        }
Beispiel #14
0
        /// <summary>
        /// Copies data from the input stream to the output stream.
        /// WARNING: sometimes it does not actually copy the content of the input stream, it attaches it to the output stream.
        /// </summary>
        /// <param name="inputStream">The stream to copy from.</param>
        /// <param name="outputStream">The stream to copy to.</param>
        /// <param name="buffer">The intermediate buffer used during copying.</param>
        public static void CopyStreamToStreamWithMinimumOperations(Stream inputStream, Stream outputStream, byte[] buffer)
        {
            GenuineChunkedStream inputGenuineChunkedStream = inputStream as GenuineChunkedStream;

            if (inputGenuineChunkedStream != null)
            {
                inputGenuineChunkedStream.WriteTo(outputStream);
                return;
            }

            int bufSize  = buffer.Length;
            int readSize = inputStream.Read(buffer, 0, bufSize);

            while (readSize > 0)
            {
                outputStream.Write(buffer, 0, readSize);
                readSize = inputStream.Read(buffer, 0, bufSize);
            }
        }
Beispiel #15
0
        /// <summary>
        /// Copies data from one stream to another.
        /// </summary>
        /// <param name="inputStream">Stream to copy from.</param>
        /// <param name="outputStream">Stream to copy to.</param>
        public static void CopyStreamToStream(Stream inputStream, Stream outputStream)
        {
            GenuineChunkedStream inputGenuineChunkedStream = inputStream as GenuineChunkedStream;

            if (inputGenuineChunkedStream != null)
            {
                inputGenuineChunkedStream.WriteTo(outputStream);
                return;
            }

            using (BufferKeeper bufferKeeper = new BufferKeeper(0))
            {
                int bufSize  = bufferKeeper.Buffer.Length;
                int readSize = inputStream.Read(bufferKeeper.Buffer, 0, bufSize);
                while (readSize > 0)
                {
                    outputStream.Write(bufferKeeper.Buffer, 0, readSize);
                    readSize = inputStream.Read(bufferKeeper.Buffer, 0, bufSize);
                }
            }
        }
        /// <summary>
        /// Sends the invocation to all registered receivers.
        /// </summary>
        /// <param name="msg">The message to be sent.</param>
        public void PerformBroadcasting(IMessage msg)
        {
            BinaryLogWriter binaryLogWriter  = GenuineLoggingServices.BinaryLogWriter;
            string          methodName       = null;
            string          invocationTarget = null;

            // the first stage of the broadcasting
            try
            {
                ArrayList listOfExcludedReceivers = new ArrayList();
                this._iMessage = msg;
                methodName     = BinaryLogWriter.ParseInvocationMethod(msg.Properties["__MethodName"] as string, msg.Properties["__TypeName"] as string);

                BinaryFormatter formatterForLocalRecipients = null;

                // serialize the message
                BinaryFormatter binaryFormatter = new BinaryFormatter(new RemotingSurrogateSelector(), new StreamingContext(StreamingContextStates.Other));
                this._messageStream = new GenuineChunkedStream(false);
                binaryFormatter.Serialize(this._messageStream, msg);

                // to trace the message if it could reach the server via several channels
                string callGuidSubstring = null;
                if (this._dispatcher.IgnoreRecurrentCalls)
                {
                    callGuidSubstring = Guid.NewGuid().ToString("N");
                }

                // LOG:
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                {
                    binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting",
                                                              LogMessageType.BroadcastInvocationInitiated, null, null, null,
                                                              binaryLogWriter[LogCategory.BroadcastEngine] > 1 ? (Stream)this._messageStream.Clone() : null,
                                                              GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                              null, null, true, this._dispatcher, this, false, null,
                                                              methodName, null,
                                                              "The broadcast invocation is initiated.");
                }

                // to prevent firing resultCollector.AllMessagesReceived event
                this.UnrepliedReceivers[_uniqueReceiverName] = null;

                object[] listOfReceiverInfo;
                this._dispatcher.GetListOfReceivers(out listOfReceiverInfo, msg, this);

                // through all recipients
                for (int i = 0; i < listOfReceiverInfo.Length; i++)
                {
                    ReceiverInfo receiverInfo = listOfReceiverInfo[i] as ReceiverInfo;
                    if (receiverInfo == null)
                    {
                        continue;
                    }

                    string mbrUri = (string)receiverInfo.MbrUri;
                    invocationTarget = mbrUri;

                    try
                    {
                        lock (receiverInfo)
                        {
                            if (this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically != 0 &&
                                receiverInfo.NumberOfFails >= this._dispatcher.MaximumNumberOfConsecutiveFailsToExcludeReceiverAutomatically)
                            {
                                // put it to the list containing receivers being excluded
                                listOfExcludedReceivers.Add(mbrUri);
                                continue;
                            }
                        }

                        // think that it'll fail
                        if (!receiverInfo.Local && receiverInfo.GeneralBroadcastSender == null)
                        {
                            lock (this)
                            {
                                this.Failed[mbrUri] = GenuineExceptions.Get_Broadcast_RemoteEndPointDidNotReplyForTimeOut();
                            }
                        }

                        if (receiverInfo.Local)
                        {
                            // call to local appdomain
                            // ignore recurrent calls
                            if (this._dispatcher.IgnoreRecurrentCalls && UniqueCallTracer.Instance.WasGuidRegistered(mbrUri + callGuidSubstring))
                            {
                                continue;
                            }

                            // we'll wait for the answer from this receiver
                            this.UnrepliedReceivers[mbrUri] = null;

                            // LOG:
                            if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                            {
                                binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting",
                                                                          LogMessageType.BroadcastRecipientInvoked, null, null, null, null,
                                                                          GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                          null, null, false, this._dispatcher, this, false, receiverInfo,
                                                                          null, null,
                                                                          "The local receiver is invoked via LocalPerformer.");
                            }

                            if (formatterForLocalRecipients == null)
                            {
                                formatterForLocalRecipients = new BinaryFormatter();
                            }

                            // fixed in 2.5.9.6
                            IMessage iLocalMessage = (IMessage)formatterForLocalRecipients.Deserialize((Stream)this._messageStream.Clone());

                            // queue task to run the call locally
                            //IMessage iLocalMessage = (IMessage) binaryFormatter.Deserialize( (Stream) this._messageStream.Clone() );
                            LocalPerformer localPerformer = new LocalPerformer(iLocalMessage, this, receiverInfo.MbrObject);
                            GenuineThreadPool.QueueUserWorkItem(new WaitCallback(localPerformer.Call), null, false);
                        }
                        else if (receiverInfo.GeneralBroadcastSender != null)
                        {
                            // call via true multicast channel
                            Stream messageToBeSent = (Stream)this._messageStream.Clone();

                            // send via real broadcast sender to the specific court
                            msg.Properties["__Uri"] = string.Empty;
                            Message message = Message.CreateOutcomingMessage(receiverInfo.GeneralBroadcastSender.ITransportContext, msg, new TransportHeaders(), messageToBeSent, false);
                            message.DestinationMarshalByRef = receiverInfo.SerializedObjRef;
                            message.GenuineMessageType      = GenuineMessageType.TrueBroadcast;

                            // to ignore recurrent calls on the remote side
                            if (this._dispatcher.IgnoreRecurrentCalls)
                            {
                                message.ITransportHeaders[Message.TransportHeadersBroadcastSendGuid] = callGuidSubstring;
                            }

                            // LOG:
                            if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                            {
                                message.ITransportHeaders[Message.TransportHeadersInvocationTarget] = invocationTarget;
                                message.ITransportHeaders[Message.TransportHeadersMethodName]       = methodName;

                                binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting",
                                                                          LogMessageType.BroadcastRecipientInvoked, null, null, null, null,
                                                                          GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                          null, null, false, this._dispatcher, this, false, receiverInfo,
                                                                          null, null,
                                                                          "Mulsticast sender is being invoked.");
                            }

                            // register to catch all the answers
                            receiverInfo.GeneralBroadcastSender.ITransportContext.IIncomingStreamHandler.RegisterResponseProcessor(message.MessageId, this);
                            // and send it
                            receiverInfo.GeneralBroadcastSender.SendMessage(message, this);
                        }
                        else
                        {
                            // send the invocation through the usual channel
                            // we'll wait for the reply
                            this.UnrepliedReceivers[mbrUri] = null;

                            // send only if this receiver is not expected to receive message via broadcast channel
                            if (receiverInfo.NeedsBroadcastSimulation)
                            {
                                // each time a new stream is created because sinks change stream position concurrently
                                Stream           messageToBeSent  = (Stream)this._messageStream.Clone();
                                TransportHeaders transportHeaders = new TransportHeaders();

                                // to ignore recurrent calls on the remote side
                                if (this._dispatcher.IgnoreRecurrentCalls)
                                {
                                    transportHeaders[Message.TransportHeadersBroadcastSendGuid] = callGuidSubstring;
                                }

                                // LOG:
                                if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                                {
                                    binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting",
                                                                              LogMessageType.BroadcastRecipientInvoked, null, null, receiverInfo.DbgRemoteHost, null,
                                                                              GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                              null, null, false, this._dispatcher, this, false, receiverInfo,
                                                                              null, null,
                                                                              "The broadcast recipient is being invoked directly.");
                                }

                                // invoke the destination MBR
                                msg.Properties["__Uri"] = receiverInfo.MbrUri;
                                transportHeaders[Message.TransportHeadersBroadcastObjRefOrCourt] = receiverInfo.SerializedObjRef;
                                transportHeaders[Message.TransportHeadersMbrUriName]             = receiverInfo.MbrUri;
                                transportHeaders[Message.TransportHeadersGenuineMessageType]     = GenuineMessageType.BroadcastEngine;
                                transportHeaders[Message.TransportHeadersInvocationTarget]       = invocationTarget;
                                transportHeaders[Message.TransportHeadersMethodName]             = methodName;
                                ClientChannelSinkStack clientChannelSinkStack = new ClientChannelSinkStack(this);
                                clientChannelSinkStack.Push(this, null);
                                receiverInfo.IClientChannelSink.AsyncProcessRequest(clientChannelSinkStack, this._iMessage, transportHeaders, messageToBeSent);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        this.ParseResult(mbrUri, null, ex);
                    }
                }

                // remove set uri from the hash to check wither the invocation finished
                this.UnrepliedReceivers.Remove(_uniqueReceiverName);
                if (this.UnrepliedReceivers.Count <= 0)
                {
                    this.AllMessagesReceived.Set();
                }

                this.StartReceiving();

                if (listOfExcludedReceivers.Count > 0)
                {
                    foreach (string uri in listOfExcludedReceivers)
                    {
                        this._dispatcher.Remove(uri);
                    }
                }
            }
            catch (Exception ex)
            {
                // LOG:
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.BroadcastEngine] > 0)
                {
                    binaryLogWriter.WriteBroadcastEngineEvent(LogCategory.BroadcastEngine, "ResultCollector.PerformBroadcasting",
                                                              LogMessageType.BroadcastInvocationInitiated, ex, null, null, null,
                                                              GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                              null, null, false, this._dispatcher, this, false, null,
                                                              invocationTarget, methodName,
                                                              "A critical failure occurred during broadcast.");
                }

                throw;
            }
        }
Beispiel #17
0
        /// <summary>
        /// Sends the message to the remote host.
        /// </summary>
        /// <param name="message">The message to be sent.</param>
        protected override void InternalSend(Message message)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            // get IP end point of the remote host
            IPEndPoint remoteEndPoint;

            if (message.Recipient.Uri != null && message.Recipient.Uri.StartsWith("_gb"))
            {
                remoteEndPoint = this._multicastTo;
            }
            else
            {
                remoteEndPoint = message.Recipient.PhysicalAddress as IPEndPoint;
            }
            if (remoteEndPoint == null)
            {
                try
                {
                    int    port;
                    string baseUrl = GenuineUtility.SplitToHostAndPort(message.Recipient.Url, out port);
                    message.Recipient.PhysicalAddress = remoteEndPoint = new IPEndPoint(GenuineUtility.ResolveIPAddress(baseUrl), port);
                }
                catch (Exception)
                {
                    throw GenuineExceptions.Get_Send_DestinationIsUnreachable(message.Recipient.ToString());
                }
            }

            Stream streamToSend = message.SerializedContent;

            // write the host URI
            if ((int)this.ITransportContext.IParameterProvider[GenuineParameter.CompatibilityLevel] > 0)
            {
                GenuineChunkedStream streamWith250Header = new GenuineChunkedStream(false);
                BinaryWriter         binaryWriter        = new BinaryWriter(streamWith250Header);
                streamWith250Header.Write(this.ITransportContext.BinaryHostIdentifier, 0, this.ITransportContext.BinaryHostIdentifier.Length);
                binaryWriter.Write((int)message.Recipient.LocalHostUniqueIdentifier);
                binaryWriter.Write((Int16)0);

                streamWith250Header.WriteStream(streamToSend);

                streamToSend = streamWith250Header;
            }

            // LOG:
            if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0)
            {
                binaryLogWriter.WriteEvent(LogCategory.Connection, "UdpConnectionManager.InternalSend",
                                           LogMessageType.MessageIsSentSynchronously, null, message, message.Recipient, null,
                                           GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                           message.ConnectionLevelSecuritySession, message.ConnectionLevelSecuritySession == null ? null : message.ConnectionLevelSecuritySession.Name,
                                           -1, 0, 0, 0, remoteEndPoint.ToString(), null, null, null,
                                           "The message is being sent synchronously to {0}.", remoteEndPoint.ToString());
            }

            // send the message
            byte[] streamId = Guid.NewGuid().ToByteArray();

            lock (_socketLock)
            {
                for (int chunkNumber = 1; ; chunkNumber++)
                {
                    // read the next chunk
                    int chunkSize = streamToSend.Read(this._sendBuffer, HEADER_SIZE, this._sendBuffer.Length - HEADER_SIZE);

                    // fill in the header
                    this._sendBuffer[0] = MessageCoder.COMMAND_MAGIC_CODE;
                    Buffer.BlockCopy(streamId, 0, this._sendBuffer, 1, 16);
                    if (chunkSize < this._sendBuffer.Length - HEADER_SIZE)
                    {
                        chunkNumber = -chunkNumber;
                    }
                    MessageCoder.WriteInt32(this._sendBuffer, 17, chunkNumber);

                    // and just send it!

                    // LOG:
                    if (binaryLogWriter != null && binaryLogWriter[LogCategory.Transport] > 0)
                    {
                        binaryLogWriter.WriteTransportContentEvent(LogCategory.Transport, "UdpConnectionManager.InternalSend",
                                                                   LogMessageType.SynchronousSendingStarted, null, message, message.Recipient,
                                                                   binaryLogWriter[LogCategory.Transport] > 1 ? new MemoryStream(GenuineUtility.CutOutBuffer(this._sendBuffer, 0, chunkSize + HEADER_SIZE)) : null,
                                                                   GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                   this.DbgConnectionId, chunkSize + HEADER_SIZE, remoteEndPoint.ToString(),
                                                                   null, null,
                                                                   "Content is sent synchronously to {0}.", remoteEndPoint.ToString());
                    }

                    this._socket.SendTo(this._sendBuffer, 0, chunkSize + HEADER_SIZE, SocketFlags.None, remoteEndPoint);

                    if (chunkNumber < 0)
                    {
                        break;
                    }
                }
            }
        }
Beispiel #18
0
        /// <summary>
        /// Initiates or continues establishing of the Security Session.
        /// </summary>
        /// <param name="input">A null reference or an incoming stream.</param>
        /// <param name="connectionLevel">Indicates whether the Security Session operates on connection level.</param>
        /// <returns>A stream containing data for sending to the remote host or a null reference if Security Session is established.</returns>
        public override GenuineChunkedStream EstablishSession(Stream input, bool connectionLevel)
        {
            // a dance is over
            if (this.IsEstablished)
            {
                return(null);
            }

            GenuineChunkedStream outputStream = null;
            var binaryFormatter = new BinaryFormatter().Safe();

            // skip the status flag
            if (connectionLevel)
            {
                if (input != null)
                {
                    input.ReadByte();
                }

                outputStream = new GenuineChunkedStream(false);
            }
            else
            {
                outputStream = this.CreateOutputStream();
            }

            lock (this)
            {
                // write session is being established flag
                BinaryWriter binaryWriter = new BinaryWriter(outputStream);
                binaryWriter.Write((bool)false);

                // remote host sent nothing, send a RSA public key
                if (input == null || input == Stream.Null)
                {
                    // serialize RSA public key
                    RSAParameters rsaParameters = this._rsaCryptoServiceProviderDecryptor.ExportParameters(false);
                    binaryFormatter.Serialize(outputStream, rsaParameters);
                    binaryFormatter.Serialize(outputStream, this._localInstanceGuid);

                    return(outputStream);
                }

                // deserialize incoming data
                Rijndael rijndael       = null;
                object   receivedObject = binaryFormatter.Deserialize(input);

                // RSA public key has been received
                if (receivedObject is RSAParameters)
                {
                    this._remoteInstanceGuid = (string)binaryFormatter.Deserialize(input);
                    if (string.Compare(this._remoteInstanceGuid, this._localInstanceGuid, false) > 0)
                    {
                        return(this.EstablishSession(Stream.Null, connectionLevel));
                    }

                    if (this.RijndaelKey == null)
                    {
                        // create Rijndael key
                        rijndael         = Rijndael.Create();
                        this.RijndaelKey = rijndael.Key;
                    }

                    // encrypt it with public rsa key
                    RSAParameters            rsaParameters = (RSAParameters)receivedObject;
                    RSACryptoServiceProvider rsaCryptoServiceProvider;
                    try
                    {
                        // try the usual way, and if fails, use the patch in the catch block
                        rsaCryptoServiceProvider = new RSACryptoServiceProvider();
                    }
                    catch
                    {
                        CspParameters CSPParam = new CspParameters();
                        CSPParam.Flags           = CspProviderFlags.UseMachineKeyStore;
                        rsaCryptoServiceProvider = new RSACryptoServiceProvider(CSPParam);
                    }
                    rsaCryptoServiceProvider.ImportParameters(rsaParameters);

                    // serialize
                    byte[] encryptedContent = RSAUtility.Encrypt(rsaCryptoServiceProvider, this.RijndaelKey);
                    binaryFormatter.Serialize(outputStream, encryptedContent);

                    return(outputStream);
                }

                // Rijndael key has been received
                if (receivedObject is byte[])
                {
                    // first of all, retrieve it
                    byte[] receivedRijndaelKey = RSAUtility.Decrypt(this._rsaCryptoServiceProviderDecryptor, (byte[])receivedObject);

                    // accept received key
                    this.RijndaelKey = receivedRijndaelKey;

                    // confirm that the session has been established
                    binaryFormatter.Serialize(outputStream, "OK");
                    this.SessionEstablished();
                    return(outputStream);
                }

                // a confirmation received that the session is established
                if (receivedObject is string)
                {
                    this.SessionEstablished();
                    return(null);
                }
            }

            throw GenuineExceptions.Get_Receive_IncorrectData();
        }
Beispiel #19
0
        /// <summary>
        /// Establishes Connection Level Security Session and gather their output into specified stream.
        /// </summary>
        /// <param name="senderInput">The input stream.</param>
        /// <param name="listenerInput">The input stream.</param>
        /// <param name="output">The output stream.</param>
        /// <param name="sender">The sender's Security Session.</param>
        /// <param name="listener">The listener's Security Session.</param>
        /// <returns>True if at least one Security Session requested sending of data.</returns>
        public bool GatherContentOfConnectionLevelSecuritySessions(Stream senderInput, Stream listenerInput, GenuineChunkedStream output, SecuritySession sender, SecuritySession listener)
        {
            bool   clssDataPresents = false;
            Stream clsseStream;

            // CLSSE info
            using (new GenuineChunkedStreamSizeLabel(output))
            {
                if (sender != null && !sender.IsEstablished)
                {
                    clsseStream = sender.EstablishSession(senderInput, true);
                    if (clsseStream != null)
                    {
                        clssDataPresents = true;
                        GenuineUtility.CopyStreamToStream(clsseStream, output);
                    }
                }
            }

            // CLSSE info
            using (new GenuineChunkedStreamSizeLabel(output))
            {
                if (listener != null && !listener.IsEstablished)
                {
                    clsseStream = listener.EstablishSession(listenerInput, true);
                    if (clsseStream != null)
                    {
                        clssDataPresents = true;
                        GenuineUtility.CopyStreamToStream(clsseStream, output);
                    }
                }
            }

            return(clssDataPresents);
        }
Beispiel #20
0
 /// <summary>
 /// Encrypts the message data and put a result into the specified output stream.
 /// </summary>
 /// <param name="input">The stream containing the serialized message.</param>
 /// <param name="output">The result stream with the data being sent to the remote host.</param>
 public override void Encrypt(Stream input, GenuineChunkedStream output)
 {
     output.WriteByte(1);
     lock (this._encryptor)
         GenuineUtility.CopyStreamToStream(new CryptoStream(new FinishReadingStream(input), this._encryptor, CryptoStreamMode.Read), output);
 }
Beispiel #21
0
        /// <summary>
        /// Initiates or continues establishing of the Security Session.
        /// </summary>
        /// <param name="input">A null reference or an incoming stream.</param>
        /// <param name="connectionLevel">Indicates whether the Security Session operates on connection level.</param>
        /// <returns>A stream containing data for sending to the remote host or a null reference if Security Session is established.</returns>
        public override GenuineChunkedStream EstablishSession(Stream input, bool connectionLevel)
        {
            BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter;
            bool            passException   = false;

            // a dance is over
            if (this.IsEstablished)
            {
                return(null);
            }

            GenuineChunkedStream outputStream = null;
            var binaryFormatter = new BinaryFormatter().Safe();

            // skip the status flag
            if (connectionLevel)
            {
                if (input != null)
                {
                    input.ReadByte();
                }
                outputStream = new GenuineChunkedStream(false);
            }
            else
            {
                outputStream = this.CreateOutputStream();
            }

            // write session is being established flag
            BinaryWriter binaryWriter = new BinaryWriter(outputStream);

            binaryWriter.Write((byte)0);

            try
            {
                lock (this)
                {
                    ZpaPacketStatusFlag zpaPacketStatusFlag;

                    if (input == Stream.Null)
                    {
                        zpaPacketStatusFlag = ZpaPacketStatusFlag.ForceInitialization;
                    }
                    else
                    {
                        zpaPacketStatusFlag = (ZpaPacketStatusFlag)input.ReadByte();
                    }

                    // LOG:
                    if (binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0)
                    {
                        binaryLogWriter.WriteEvent(LogCategory.Security, "SecuritySession_ZpaServer.EstablishSession",
                                                   LogMessageType.SecuritySessionEstablishing, null, null, this.Remote, null,
                                                   GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                   this, this.Name, -1,
                                                   0, 0, 0, Enum.Format(typeof(ZpaPacketStatusFlag), zpaPacketStatusFlag, "g"), null, null, null,
                                                   "ZPA Server Session is being established. Status: {0}.", Enum.Format(typeof(ZpaPacketStatusFlag), zpaPacketStatusFlag, "g"));
                    }

                    switch (zpaPacketStatusFlag)
                    {
                    case ZpaPacketStatusFlag.ExceptionThrown:
                        Exception receivedException = GenuineUtility.ReadException(input);

#if DEBUG
//							this.Remote.ITransportContext.IEventLogger.Log(LogMessageCategory.Security, receivedException, "SecuritySession_ZpaServer.EstablishSession",
//								null, "Zero Proof Authorization ends up with an exception at the remote host. Remote host: {0}.",
//								this.Remote.ToString());
#endif

                        this.Remote.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(
                                                                                     GenuineEventType.SecuritySessionFailed, receivedException, this.Remote, this));

                        this.DispatchException(receivedException);
                        passException = true;
                        throw receivedException;

                    case ZpaPacketStatusFlag.ForceInitialization:
                        // send the sault to the remote host
                        binaryWriter.Write((byte)ZpaPacketStatusFlag.Salt);
                        binaryFormatter.Serialize(outputStream, this.Salt);
                        return(outputStream);

                    case ZpaPacketStatusFlag.HashedPassword:
                        // the the password
                        this._login = binaryFormatter.Deserialize(input);
                        string password = this.KeyProvider_ZpaServer.IAuthorizationManager.GetPassword(this._login);

                        // and check on the hash
                        byte[] calculatedHash = (byte[])binaryFormatter.Deserialize(input);
                        byte[] expectedHash   = ZeroProofAuthorizationUtility.CalculateDefaultKeyedHash(password, this.Salt);

                        if (!ZeroProofAuthorizationUtility.CompareBuffers(calculatedHash, expectedHash, expectedHash.Length))
                        {
                            throw GenuineExceptions.Get_Security_PasswordKnowledgeIsNotProved();
                        }

                        // ok the hash is correct. Complete the authorization

                        this.SetupSecurityAlgorithms(password);
                        this.SessionEstablished();

                        binaryWriter.Write((byte)ZpaPacketStatusFlag.SessionEstablished);
                        return(outputStream);

                    case ZpaPacketStatusFlag.Salt:
                    case ZpaPacketStatusFlag.SessionEstablished:
                        throw GenuineExceptions.Get_Processing_LogicError(
                                  string.Format("The remote host must have the Security Session of the type SecuritySession_ZpaServer registered with the name {0}. SecuritySession_ZpaServer never sends {1} packet marker.",
                                                this.Name, Enum.GetName(typeof(ZpaPacketStatusFlag), zpaPacketStatusFlag)));
                    }
                }
            }
            catch (Exception opEx)
            {
#if DEBUG
//				this.Remote.ITransportContext.IEventLogger.Log(LogMessageCategory.Security, opEx, "SecuritySession_SspiServer.EstablishSession",
//					null, "Exception was thrown while establishing security context.");
#endif

                if (this.Remote != null)
                {
                    this.Remote.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(
                                                                                 GenuineEventType.SecuritySessionFailed, opEx, this.Remote, this));
                }

                this.DispatchException(opEx);
                if (passException)
                {
                    throw;
                }

                binaryWriter.Write((byte)ZpaPacketStatusFlag.ExceptionThrown);
                binaryFormatter.Serialize(outputStream, opEx);
                return(outputStream);
            }

            return(null);
        }
Beispiel #22
0
        /// <summary>
        /// Handles incoming message (message, response or event).
        /// </summary>
        /// <param name="message">The message to handle.</param>
        public void HandleIncomingMessage(Message message)
        {
            BinaryLogWriter binaryLogWriter = message.ITransportContext.BinaryLogWriter;

            try
            {
                ServerChannelSinkStack stack = new ServerChannelSinkStack();
                stack.Push(this, message);

                ITransportHeaders responseHeaders;
                Stream            responseStream;
                IMessage          responseMsg;

                // FIX: 2.5.8 removing the application name from the object URI
                string applicationName = RemotingConfiguration.ApplicationName;
                if (applicationName != null)
                {
                    string uri = (string)message.ITransportHeaders["__RequestUri"];
                    if (uri.Length > applicationName.Length && uri.StartsWith(applicationName))
                    {
                        int sizeToBeCut = applicationName.Length + (uri[applicationName.Length] == '/' ? 1 : 0);
                        uri = uri.Substring(sizeToBeCut);
                        message.ITransportHeaders["__RequestUri"] = uri;
                    }
                }

                message.ITransportHeaders["__CustomErrorsEnabled"]       = false;
                message.ITransportHeaders[CommonTransportKeys.IPAddress] = message.Sender.PhysicalAddress is IPEndPoint ? ((IPEndPoint)message.Sender.PhysicalAddress).Address : message.Sender.PhysicalAddress;

                // LOG: put down the log record
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0)
                {
                    binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineUniversalServerTransportSink.HandleIncomingMessage",
                                               LogMessageType.MessageRequestInvoking, null, message, message.Sender,
                                               null,
                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                               null, null, -1, GenuineUtility.TickCount, 0, 0, null, null, null, null,
                                               "The .NET Remoting request is being invoked.");
                }

                ServerProcessing serverProcessing = this._nextChannelSink.ProcessMessage(stack, null, message.ITransportHeaders, message.Stream, out responseMsg, out responseHeaders, out responseStream);

                switch (serverProcessing)
                {
                case ServerProcessing.Complete:
                    Message reply = new Message(message, responseHeaders, responseStream);

                    // LOG: put down the log record
                    if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0)
                    {
                        string invocationTarget = responseMsg.Properties["__Uri"] as string;
                        string methodName       = BinaryLogWriter.ParseInvocationMethod(responseMsg.Properties["__MethodName"] as string, responseMsg.Properties["__TypeName"] as string);
                        binaryLogWriter.WriteMessageCreatedEvent("GenuineUniversalServerTransportSink.HandleIncomingMessage",
                                                                 LogMessageType.MessageCreated, null, reply, false, reply.Recipient,
                                                                 this.ITransportContext.BinaryLogWriter[LogCategory.MessageProcessing] > 1 ? reply.Stream : null,
                                                                 invocationTarget, methodName,
                                                                 GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, -1, -1, null, -1, null,
                                                                 "The response message has been created.");

                        reply.ITransportHeaders[Message.TransportHeadersInvocationTarget] = invocationTarget;
                        reply.ITransportHeaders[Message.TransportHeadersMethodName]       = methodName;

                        binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineUniversalServerTransportSink.HandleIncomingMessage",
                                                   LogMessageType.MessageRequestInvoked, null, reply, message.Sender,
                                                   null,
                                                   GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                   null, null, -1, GenuineUtility.TickCount, 0, message.SeqNo, null, null, null, null,
                                                   "The .NET Remoting invocation has been performed.");
                    }

                    message.ITransportContext.ConnectionManager.Send(reply);
                    break;

                case ServerProcessing.Async:
                    // asyncProcessResponse will be called later
                    break;

                case ServerProcessing.OneWay:
                    // LOG: put down the log record
                    if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0)
                    {
                        binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineUniversalServerTransportSink.HandleIncomingMessage",
                                                   LogMessageType.MessageRequestInvoked, null, null, message.Sender,
                                                   null,
                                                   GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                   null, null, -1, GenuineUtility.TickCount, 0, message.SeqNo, null, null, null, null,
                                                   "One-way .NET Remoting invocation has been performed. No response is available.");
                    }
                    break;
                }
            }
            catch (Exception ex)
            {
                try
                {
                    // LOG: put down the log record
                    if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0)
                    {
                        binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineUniversalServerTransportSink.HandleIncomingMessage",
                                                   LogMessageType.MessageRequestInvoking, ex, message, message.Sender,
                                                   null,
                                                   GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                   null, null, -1, 0, 0, 0, null, null, null, null,
                                                   "The .NET Remoting request resulted in exception. The exception is being sent back.");
                    }

                    // return this exception as a result
                    BinaryFormatter      binaryFormatter     = new BinaryFormatter();
                    GenuineChunkedStream serializedException = new GenuineChunkedStream(false);
                    binaryFormatter.Serialize(serializedException, ex);

                    Message reply = new Message(message, new TransportHeaders(), serializedException);
                    reply.ContainsSerializedException = true;
                    this.ITransportContext.ConnectionManager.Send(reply);
                }
                catch (Exception internalEx)
                {
                    // It's a destiny not to deliver an exception back to the caller

                    // LOG: put down the log record
                    if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0)
                    {
                        binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineUniversalServerTransportSink.HandleIncomingMessage",
                                                   LogMessageType.MessageRequestInvoking, internalEx, message, message.Sender,
                                                   null,
                                                   GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                   null, null, -1, 0, 0, 0, null, null, null, null,
                                                   "The source exception cannot be sent over the network. Both exceptions are ignored.");
                    }
                }
            }
        }
        /// <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;
            }
        }
Beispiel #24
0
        /// <summary>
        /// Initiates or continues establishing of the Security Session.
        /// Implementation notes: receiving of exceptions no more breaks up the connection like
        /// it was in the previous versions.
        /// </summary>
        /// <param name="input">A null reference or an incoming stream.</param>
        /// <param name="connectionLevel">Indicates whether the Security Session operates on connection level.</param>
        /// <returns>A stream containing data for sending to the remote host or a null reference if Security Session is established.</returns>
        public override GenuineChunkedStream EstablishSession(Stream input, bool connectionLevel)
        {
            bool passException = false;

            // a dance is over
            if (this.IsEstablished)
            {
                return(null);
            }

            GenuineChunkedStream outputStream    = null;
            BinaryFormatter      binaryFormatter = new BinaryFormatter();

            // skip the status flag
            if (connectionLevel)
            {
                if (input != null)
                {
                    input.ReadByte();
                }
                outputStream = new GenuineChunkedStream(false);
            }
            else
            {
                outputStream = this.CreateOutputStream();
            }

            // write session is being established flag
            BinaryWriter binaryWriter = new BinaryWriter(outputStream);

            binaryWriter.Write((byte)0);

            try
            {
                lock (this)
                {
                    if (input == Stream.Null)
                    {
                        // request establishing the Security Session
                        binaryWriter.Write((byte)SspiPacketStatusFlags.ForceInitialization);
                        return(outputStream);
                    }

                    SspiPacketStatusFlags sspiPacketStatusFlags = (SspiPacketStatusFlags)input.ReadByte();
                    switch (sspiPacketStatusFlags)
                    {
                    case SspiPacketStatusFlags.InitializeFromScratch:
                    case SspiPacketStatusFlags.ContinueAuthentication:
                        if (sspiPacketStatusFlags == SspiPacketStatusFlags.InitializeFromScratch)
                        {
                            this.SspiSecurityContext = new SspiServerSecurityContext(this.KeyProvider_SspiServer);
                        }

                        // continue building a security context
                        GenuineChunkedStream sspiData = new GenuineChunkedStream(false);
                        this.SspiSecurityContext.BuildUpSecurityContext(input, sspiData);

                        if (sspiData.Length == 0)
                        {
                            // SSPI session is built up
                            outputStream.WriteByte((byte)SspiPacketStatusFlags.SessionEstablished);
                            this.SessionEstablished();
                        }
                        else
                        {
                            outputStream.WriteByte((byte)SspiPacketStatusFlags.ContinueAuthentication);
                            outputStream.WriteStream(sspiData);
                        }
                        return(outputStream);

                    case SspiPacketStatusFlags.ExceptionThrown:
                        Exception receivedException = this.ReadException(input);

#if DEBUG
//							this.Remote.ITransportContext.IEventLogger.Log(LogMessageCategory.Security, receivedException, "SecuritySession_SspiServer.EstablishSession",
//								null, "SSPI initialization ends up with an exception at the remote host. Remote host: {0}.",
//								this.Remote.ToString());
#endif

                        if (this.Remote != null)
                        {
                            this.Remote.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(
                                                                                         GenuineEventType.SecuritySessionFailed, receivedException, this.Remote, this));
                        }

                        this.DispatchException(receivedException);
                        passException = true;
                        throw receivedException;

                    case SspiPacketStatusFlags.ForceInitialization:
                        throw GenuineExceptions.Get_Processing_LogicError(
                                  string.Format("The remote host must have the Security Session of the type SecuritySession_SspiClient registered with the name {0}. SecuritySession_SspiClient never sends SspiPacketMark.ForceInitialization packet mark.",
                                                this.Name));

                    case SspiPacketStatusFlags.SessionEstablished:
                        this.SessionEstablished();
                        break;
                    }
                }
            }
            catch (Exception opEx)
            {
#if DEBUG
//				this.Remote.ITransportContext.IEventLogger.Log(LogMessageCategory.Security, opEx, "SecuritySession_SspiServer.EstablishSession",
//					null, "Exception was thrown while establishing security context.");
#endif

                if (this.Remote != null)
                {
                    this.Remote.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(
                                                                                 GenuineEventType.SecuritySessionFailed, opEx, this.Remote, this));
                }

                this.DispatchException(opEx);
                if (passException)
                {
                    throw;
                }

                binaryWriter.Write((byte)SspiPacketStatusFlags.ExceptionThrown);
                binaryFormatter.Serialize(outputStream, opEx);
                return(outputStream);
            }

            return(null);
        }
        /// <summary>
        /// Completes the HTTP request.
        /// </summary>
        /// <param name="ar">The result of the HTTP request.</param>
        private void OnRequestCompleted(IAsyncResult ar)
        {
            HttpWebResponse httpWebResponse = null;
            Stream          inputStream     = null;
            ConnectionInfo  connectionInfo  = null;

            try
            {
                connectionInfo = (ConnectionInfo)ar.AsyncState;
                HttpWebRequest httpWebRequest = connectionInfo.HttpWebRequest;
#if (FRM20)
                // timeout has been already set
                try
                {
                    httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                }
                catch (WebException ex)
                {
                    if (ex.Status == WebExceptionStatus.Timeout)
                    {
                        return;
                    }
                }
#else
                httpWebResponse = (HttpWebResponse)httpWebRequest.EndGetResponse(ar);
#endif
                this.Remote.Renew(this._hostRenewingSpan, false);

                // process the content
                inputStream = httpWebResponse.GetResponseStream();

#if DEBUG
//				if (this.ITransportContext.IEventLogger.AcceptBinaryData)
//				{
//					byte[] content = new byte[(int) httpWebResponse.ContentLength];
//					GenuineUtility.ReadDataFromStream(inputStream, content, 0, content.Length);
//
//					this.ITransportContext.IEventLogger.Log(LogMessageCategory.Traffic, null, "HttpInvocationConnection.OnRequestCompleted",
//						content, "The content of the response received by the HttpInvocationConnection. Size: {0}.", content.Length);
//					inputStream = new MemoryStream(content, false);
//				}
#endif

                BinaryReader   binaryReader = new BinaryReader(inputStream);
                string         serverUri;
                int            sequenceNo;
                HttpPacketType httpPacketType;
                int            remoteHostUniqueIdentifier;
                HttpMessageCoder.ReadResponseHeader(binaryReader, out serverUri, out sequenceNo, out httpPacketType, out remoteHostUniqueIdentifier);

#if DEBUG
//				this.ITransportContext.IEventLogger.Log(LogMessageCategory.TransportLayer, null, "HttpInvocationConnection.OnRequestCompleted",
//					null, "The invocation request returned. Server uri: {0}. Sequence no: {1}. Packet type: {2}. Content-encoding: {3}. Content-length: {4}. Protocol version: {5}. Response uri: \"{6}\". Server: \"{7}\". Status code: {8}. Status description: \"{9}\".",
//					serverUri, sequenceNo, Enum.Format(typeof(HttpPacketType), httpPacketType, "g"),
//					httpWebResponse.ContentEncoding, httpWebResponse.ContentLength,
//					httpWebResponse.ProtocolVersion, httpWebResponse.ResponseUri,
//					httpWebResponse.Server, httpWebResponse.StatusCode, httpWebResponse.StatusDescription);
#endif

                // if the remote host has asked to terminate a connection
                if (httpPacketType == HttpPacketType.ClosedManually || httpPacketType == HttpPacketType.Desynchronization || httpPacketType == HttpPacketType.SenderError)
                {
                    throw GenuineExceptions.Get_Receive_ConnectionClosed();
                }

                // skip the first byte
                if (binaryReader.ReadByte() != 0)
                {
                    if (!connectionInfo.Message.IsOneWay)
                    {
//						this.ITransportContext.IEventLogger.Log(LogMessageCategory.FatalError, GenuineExceptions.Get_Processing_LogicError("The invocation response doesn't contain any messages."), "HttpInvocationConnection.OnRequestCompleted",
//							null, "The HTTP response doesn't contain content. The response to the request was not received.");
                    }
                }
                else
                {
                    // fetch and process the response messages
                    using (BufferKeeper bufferKeeper = new BufferKeeper(0))
                    {
                        using (LabelledStream labelledStream = new LabelledStream(this.ITransportContext, inputStream, bufferKeeper.Buffer))
                        {
                            GenuineChunkedStream receivedRequest = new GenuineChunkedStream(true);
                            GenuineUtility.CopyStreamToStream(labelledStream, receivedRequest);
                            this.ITransportContext.IIncomingStreamHandler.HandleMessage(receivedRequest, this.Remote, GenuineConnectionType.Invocation, string.Empty, -1, true, null, null, null);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
//				this.ITransportContext.IEventLogger.Log(LogMessageCategory.Error, ex, "HttpInvocationConnection.OnRequestCompleted",
//					null, "Exception occurred during receiving a response to an invocation request.");

                // dispatch the exception to the caller context
                if (connectionInfo != null)
                {
                    this.ITransportContext.IIncomingStreamHandler.DispatchException(connectionInfo.Message, ex);
                }
            }
            finally
            {
                if (inputStream != null)
                {
                    inputStream.Close();
                }
                if (httpWebResponse != null)
                {
                    httpWebResponse.Close();
                }

                // release the connection
                if (connectionInfo != null)
                {
                    this.ReleaseConnectionEntry(connectionInfo.Index);
                }
            }
        }
        /// <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>
        /// 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>
 /// Encrypts the message data and put a result into the specified output stream.
 /// </summary>
 /// <param name="input">The stream containing the serialized message.</param>
 /// <param name="output">The result stream with the data being sent to the remote host.</param>
 public override void Encrypt(Stream input, GenuineChunkedStream output)
 {
     output.WriteStream(input);
 }
 /// <summary>
 /// Encrypts the message data and put a result into the specified output stream.
 /// </summary>
 /// <param name="input">The stream containing the serialized message.</param>
 /// <param name="output">The result stream with the data being sent to the remote host.</param>
 public abstract void Encrypt(Stream input, GenuineChunkedStream output);