Exemple #1
0
        /// <summary>
        /// Sends the content to the specified remote host and returns a response sent by the remote
        /// host in reply.
        /// </summary>
        /// <param name="destination">The remote host.</param>
        /// <param name="serviceName">The name of the service.</param>
        /// <param name="content">The content.</param>
        /// <returns>The response.</returns>
        public Stream SendSync(HostInformation destination, string serviceName, Stream content)
        {
            // create the message
            Message message = new Message(this.ITransportContext, destination, 0, new TransportHeaders(), content);

            message.IsSynchronous           = true;
            message.GenuineMessageType      = GenuineMessageType.ExternalStreamConsumer;
            message.DestinationMarshalByRef = serviceName;

            // register the response catcher
            SyncResponseProcessorWithEvent syncResponseProcessorWithEvent = new SyncResponseProcessorWithEvent(message);

            this.ITransportContext.IIncomingStreamHandler.RegisterResponseProcessor(message.MessageId, syncResponseProcessorWithEvent);

            // and send the message
            this.ITransportContext.ConnectionManager.Send(message);

            int timeSpanInMilliseconds = GenuineUtility.GetMillisecondsLeft(message.FinishTime);

            if (timeSpanInMilliseconds <= 0)
            {
                throw GenuineExceptions.Get_Send_ServerDidNotReply();
            }
            if (!syncResponseProcessorWithEvent.IsReceivedEvent.WaitOne(timeSpanInMilliseconds, false))
            {
                throw GenuineExceptions.Get_Send_ServerDidNotReply();
            }

            if (syncResponseProcessorWithEvent.DispatchedException != null)
            {
                throw OperationException.WrapException(syncResponseProcessorWithEvent.DispatchedException);
            }
            return(syncResponseProcessorWithEvent.Response.Stream);
        }
        /// <summary>
        /// Reads data from the socket.
        /// </summary>
        /// <param name="buffer">An array of type Byte that is the storage location for received data.</param>
        /// <param name="offset">The location in buffer to store the received data.</param>
        /// <param name="count">The number of bytes to receive.</param>
        /// <returns>The number of bytes read.</returns>
        public int ReadFromSocket(byte[] buffer, int offset, int count)
        {
            BinaryLogWriter binaryLogWriter = this._tcpConnectionManager.ITransportContext.BinaryLogWriter;

            try
            {
                int millisecondsRemained = GenuineUtility.GetMillisecondsLeft(this._receiveTimeout);
                if (millisecondsRemained <= 0)
                {
                    throw GenuineExceptions.Get_Send_ServerDidNotReply();
                }

                this._tcpSocketInfo.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, millisecondsRemained);
                int bytesReceived = this._tcpSocketInfo.Socket.Receive(buffer, offset, count, SocketFlags.None);

                // LOG:
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0)
                {
                    binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "SyncSocketReadingStream.ReadFromSocket",
                                                               LogMessageType.LowLevelTransport_SyncReceivingCompleted, null, null, this._tcpSocketInfo.Remote,
                                                               binaryLogWriter[LogCategory.LowLevelTransport] > 1 ? new MemoryStream(buffer, offset, bytesReceived) : null,
                                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                               this._tcpSocketInfo.DbgConnectionId, bytesReceived,
                                                               this._tcpSocketInfo.Socket.RemoteEndPoint.ToString(), null, null,
                                                               "Socket.Receive(). Bytes received: {0}.", bytesReceived);
                }

                this._tcpConnectionManager.IncreaseBytesReceived(bytesReceived);
                return(bytesReceived);
            }
            catch (Exception ex)
            {
                // LOG:
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0)
                {
                    binaryLogWriter.WriteEvent(LogCategory.LowLevelTransport, "SyncSocketReadingStream.ReadFromSocket",
                                               LogMessageType.LowLevelTransport_SyncReceivingCompleted, ex, null, this._tcpSocketInfo.Remote, null,
                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                               null, null, this._tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                               "Socket.Receive() failed.");
                }

                throw;
            }
        }
        /// <summary>
        /// Sends a message to the remote host.
        /// </summary>
        /// <param name="message">The message to be sent.</param>
        public void Send(Message message)
        {
#if TRIAL
            _messagesBeingSent[message.MessageId] = message;
#endif

            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            try
            {
                using (new ReaderAutoLocker(this._disposeLock))
                {
                    if (this._disposed)
                    {
                        throw OperationException.WrapException(this._disposeReason);
                    }
                }

                SecuritySession session = null;

                if (this._disposed)
                {
                    throw OperationException.WrapException(this._disposeReason);
                }

                // get the security session descriptor
                if (message.SecuritySessionParameters == null)
                {
                    SecuritySessionParameters securitySessionParameters = SecuritySessionServices.GetCurrentSecurityContext();
                    if (securitySessionParameters == null)
                    {
                        securitySessionParameters = message.Recipient.SecuritySessionParameters;
                    }
                    if (securitySessionParameters == null)
                    {
                        securitySessionParameters = this.ITransportContext.SecuritySessionParameters;
                    }
                    if (securitySessionParameters == null)
                    {
                        securitySessionParameters = SecuritySessionServices.DefaultSecuritySession;
                    }
                    message.SecuritySessionParameters = securitySessionParameters;
                }

                // LOG:
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0)
                {
                    binaryLogWriter.WriteSecuritySessionParametersEvent("ConnectionManager.Send",
                                                                        LogMessageType.SecuritySessionParametersAssembled, null, message, message.Recipient,
                                                                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                        message.SecuritySessionParameters,
                                                                        "Security Session Parameters have been assembled.");
                }

                // determine the type of sending
                message.IsSynchronous = (message.SecuritySessionParameters.Attributes & SecuritySessionAttributes.ForceSync) != 0 ||
                                        (message.IsSynchronous && (message.SecuritySessionParameters.Attributes & SecuritySessionAttributes.ForceAsync) == 0);

                // the time until invocation times out
                if (!message.FinishTime_Initialized)
                {
                    TimeSpan messageTimeout = message.SecuritySessionParameters.Timeout;
                    if (messageTimeout == TimeSpan.MinValue)
                    {
                        messageTimeout = (TimeSpan)this.ITransportContext.IParameterProvider[GenuineParameter.InvocationTimeout];
                    }
                    message.FinishTime = GenuineUtility.GetTimeout(messageTimeout);

                    message.FinishTime_Initialized = true;
                }

                // checks whether the message has been already processed by Security Session
                if (message.SerializedContent == null)
                {
                    session = message.Recipient.GetSecuritySession(message.SecuritySessionParameters.Name, this.ITransportContext.IKeyStore);
                    if (!session.IsEstablished)
                    {
                        if (binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0)
                        {
                            binaryLogWriter.WriteEvent(LogCategory.Security, "ConnectionManager.Send",
                                                       LogMessageType.SecuritySessionHasNotBeenEstablishedYet, null, message, message.Recipient, null,
                                                       GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                       session, session.Name, -1, 0, 0, 0, null, null, null, null,
                                                       "The requested Security Session is not established.");
                        }

                        session.InitiateEstablishingSecuritySession(message.SecuritySessionParameters);

                        // if it's a sync sending, then wait until security session will be established
                        if (message.IsSynchronous)
                        {
                            int timeSpanToWait = GenuineUtility.GetMillisecondsLeft(message.FinishTime);
                            if (timeSpanToWait <= 0)
                            {
                                throw GenuineExceptions.Get_Send_ServerDidNotReply();
                            }

                            // wait until Security Session will be established or a failure will be detected
                            int firedEvent = 0;
                            if (message.CancelSending != null)
                            {
                                firedEvent = WaitHandle.WaitAny(new WaitHandle[] { session.IsEstablishedEvent, session.Failed, message.CancelSending }, timeSpanToWait, false);
                            }
                            else
                            {
                                firedEvent = WaitHandle.WaitAny(new WaitHandle[] { session.IsEstablishedEvent, session.Failed }, timeSpanToWait, false);
                            }

                            if (firedEvent == WaitHandle.WaitTimeout)
                            {
                                throw GenuineExceptions.Get_Send_ServerDidNotReply();
                            }

                            // analyze the problem, if any
                            Exception exception = session.ReasonOfFailure;
                            if (firedEvent == 1)
                            {
                                if (exception != null)
                                {
                                    throw OperationException.WrapException(exception);
                                }
                                else
                                {
                                    throw GenuineExceptions.Get_Security_ContextWasNotEstablished(session.Name);
                                }
                            }

                            // if the message has been cancelled, let the sender to understand the reason
                            if (firedEvent == 2)
                            {
                                return;
                            }
                        }
                        else if (!session.IsEstablished)
                        {
                            // it's async and SS still isn't established
                            session.PutMessageToAwaitingQueue(message);
                            return;
                        }
                    }
                }

                // if serialization is necessary
                if (message.SerializedContent == null)
                {
                    // serialize the message
                    GenuineChunkedStream serializedMessageStream = new GenuineChunkedStream(false);
                    MessageCoder.Serialize(serializedMessageStream, message, (message.SecuritySessionParameters.Attributes & SecuritySessionAttributes.EnableCompression) != 0);

                    // save the name of the Security Session
                    GenuineChunkedStream resultStream = new GenuineChunkedStream(false);
                    BinaryWriter         writer       = new BinaryWriter(resultStream);
                    writer.Write(message.SecuritySessionParameters.Name);
                    session.Encrypt(serializedMessageStream, resultStream);
                    message.SerializedContent = resultStream;

                    // LOG: put down the log record
                    if (binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0)
                    {
                        binaryLogWriter.WriteEvent(LogCategory.Security, "ConnectionManager.Send",
                                                   LogMessageType.SecuritySessionApplied, null, message, message.Recipient,
                                                   binaryLogWriter[LogCategory.Security] > 1 ? message.SerializedContent : null,
                                                   GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, session,
                                                   session.Name, -1, 0, 0, 0, null, null, null, null,
                                                   "The message has been processed by the established Security Session.");
                    }
                }

#if TRIAL
                if (message.MessageId > 3005)
                {
                    throw GenuineExceptions.Get_Channel_TrialConditionExceeded("The maximum number of messages restriction has been exceeded. You can not send more than 3000 messages using TRIAL version.");
                }
#endif

                message.Sender = this.Local;
                this.InternalSend(message);
            }
            catch (Exception ex)
            {
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0)
                {
                    binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "ConnectionManager.Send",
                                               LogMessageType.Error, ex, message, message.Recipient, null,
                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                               null, null, -1, 0, 0, 0, null, null, null, null,
                                               "An exception occurred while processing the message.");
                }

                throw;
            }
        }
        /// <summary>
        /// Requests message processing from the current sink.
        /// </summary>
        /// <param name="msg">The message to process.</param>
        /// <param name="requestHeaders">The headers to add to the outgoing message heading to the server.</param>
        /// <param name="requestStream">The stream headed to the transport sink.</param>
        /// <param name="responseHeaders">When this method returns, contains an ITransportHeaders interface that holds the headers that the server returned. This parameter is passed uninitialized.</param>
        /// <param name="responseStream">When this method returns, contains a Stream coming back from the transport sink. This parameter is passed uninitialized.</param>
        public void ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream,
                                   out ITransportHeaders responseHeaders, out Stream responseStream)
        {
            BinaryLogWriter   binaryLogWriter   = this.ITransportContext.BinaryLogWriter;
            ITransportContext iTransportContext = this.ITransportContext;

            if (!GenuineUtility.CheckUrlOnConnectivity(this._recipientUri))
            {
                // get the transport context from the Uri Storage
                iTransportContext = UriStorage.GetTransportContext(this._recipientUri);
                if (iTransportContext == null)
                {
                    iTransportContext = this.ITransportContext;
                }
            }

            Message message = Message.CreateOutcomingMessage(iTransportContext, msg, requestHeaders, requestStream, true);

            try
            {
                message.Recipient = iTransportContext.KnownHosts[this._recipientUri];

                // LOG: put down the log record
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0)
                {
                    binaryLogWriter.WriteMessageCreatedEvent("GenuineTcpClientTransportSink.ProcessMessage",
                                                             LogMessageType.MessageCreated, null, message, true, message.Recipient,
                                                             this.ITransportContext.BinaryLogWriter[LogCategory.MessageProcessing] > 1 ? message.Stream : null,
                                                             msg.Properties["__Uri"] as string, BinaryLogWriter.ParseInvocationMethod(msg.Properties["__MethodName"] as string, msg.Properties["__TypeName"] as string),
                                                             GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, -1, -1, null, -1, null,
                                                             "Synchronous .NET Remoting invocaiton is being initiated.");

                    message.ITransportHeaders[Message.TransportHeadersInvocationTarget] = msg.Properties["__Uri"] as string;
                    message.ITransportHeaders[Message.TransportHeadersMethodName]       = BinaryLogWriter.ParseInvocationMethod(msg.Properties["__MethodName"] as string, msg.Properties["__TypeName"] as string);

                    binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineTcpClientTransportSink.ProcessMessage",
                                               LogMessageType.MessageRequestInvoking, null, message, message.Recipient,
                                               null,
                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                               null, null, -1, GenuineUtility.TickCount, 0, 0, null, null, null, null,
                                               "The .NET Remoting synchronous invocation has been made.");
                }

                SyncSinkStackResponseProcessor syncSinkStackResponseProcessor = new SyncSinkStackResponseProcessor(iTransportContext, message);
                iTransportContext.IIncomingStreamHandler.RegisterResponseProcessor(message.MessageId, syncSinkStackResponseProcessor);
                message.CancelSending = syncSinkStackResponseProcessor.IsReceivedEvent;

                try
                {
                    // send the message or initiate the sending
                    iTransportContext.ConnectionManager.Send(message);
                }
                catch (Exception ex)
                {
                    // if it's a response processor's problem, force its exception to be fired
                    if (syncSinkStackResponseProcessor.DispatchedException != null)
                    {
                        throw OperationException.WrapException(syncSinkStackResponseProcessor.DispatchedException);
                    }

                    syncSinkStackResponseProcessor.DispatchException(ex);
                    throw;
                }

                if (!GenuineUtility.WaitOne(syncSinkStackResponseProcessor.IsReceivedEvent, GenuineUtility.GetMillisecondsLeft(message.FinishTime)))
                {
                    throw GenuineExceptions.Get_Send_ServerDidNotReply();
                }
                if (syncSinkStackResponseProcessor.DispatchedException != null)
                {
                    throw OperationException.WrapException(syncSinkStackResponseProcessor.DispatchedException);
                }

                // LOG: put down the log record
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0)
                {
                    binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineTcpClientTransportSink.ProcessMessage",
                                               LogMessageType.MessageDispatched, null, syncSinkStackResponseProcessor.Response, syncSinkStackResponseProcessor.Response.Sender,
                                               null,
                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                               null, null, -1,
                                               GenuineUtility.TickCount, 0, message.SeqNo, null, null, null, null,
                                               "The .NET Remoting synchronous invocation has been completed.");
                }

                responseHeaders = syncSinkStackResponseProcessor.Response.ITransportHeaders;
                responseStream  = syncSinkStackResponseProcessor.Response.Stream;
            }
            catch (Exception ex)
            {
                // LOG: put down the log record
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0)
                {
                    binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineTcpClientTransportSink.ProcessMessage",
                                               LogMessageType.MessageDispatched, ex, message, message.Recipient, null,
                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1,
                                               GenuineUtility.TickCount, 0, message.SeqNo, null, null, null, null,
                                               "The exception is dispatched to the caller context.");
                }

                throw;
            }
        }