예제 #1
0
        /// <summary>
        /// Helper static method, allowing to duplicate a message instance.
        /// It will duplicate the message, ONLY if the message is marked as "TransportByReference == false"
        /// or mandatoryDuplication is true.
        /// </summary>
        public static Message DuplicateMessage(Message message, bool mandatoryDuplication)
        {
            //if (mandatoryDuplication == false && message.TransportByReference)
            //{
            //    return message;
            //}

            //if (message is ICloneable)
            //{
            //    return (Message)((ICloneable)message).Clone();
            //}

            MessageContainer container;

            try
            {
                container = new MessageContainer();
                container.SerializeMessage(message);
            }
            catch (Exception exception)
            {
                TracerHelper.TraceError("Exception in message duplication [" + exception.Message + "].");
                throw;
            }

            return(container.CreateMessageInstance());
        }
예제 #2
0
        /// <summary>
        ///
        /// </summary>
        protected virtual void HandleResponseMessage(TransportMessage message)
        {
            SessionResults respondedSession = null;

            // First - check if this is a responce to a currently pending session.
            lock (_communicationSessions)
            {
                string requestMessageInfo = string.Empty;
                if (message is ResponseMessage)
                {
                    requestMessageInfo = ((ResponseMessage)message).RequestMessageTypeName;
                }

                if (_communicationSessions.ContainsKey(message.TransportInfo.CurrentTransportInfo.Value.Id) == false)
                {
                    TracerHelper.TraceError("Response received to a session that is not pending [from " + message.TransportInfo.OriginalSenderId.Value.Id.Print() + " to " + this.SubscriptionClientID.Id.Print() + "]. Message [" + message.GetType().Name + " responding to " + requestMessageInfo + "] dumped.");
                    return;
                }

                respondedSession = _communicationSessions[message.TransportInfo.CurrentTransportInfo.Value.Id];
            }

            // Clear off the sessioning Transport Info that just brough it back as well.
            message.TransportInfo.PopTransportInfo();

            respondedSession.ReceiveResponse(message);
        }
예제 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="entity"></param>
        public void AddExecutionEntity(ExecutionEntity entity)
        {
            TracerHelper.TraceEntry();
            lock (this)
            {
                if (_pendingEntities.Count > _maxPendingExecutionItems)
                {
                    TracerHelper.TraceError("Too many pending entities in system. Some older entities are being dropped.");
                    if ((DateTime.Now - _maxPendingItemsWarningShownTime) > _warningsTimeSpan)
                    {
                        _maxPendingItemsWarningShownTime = DateTime.Now;
                        SystemMonitor.Error("Too many pending entities in system. Some older entities are being dropped.");
                    }

                    // Loose the oldest entity in line.
                    _timeOutMonitor.RemoveEntity(_pendingEntities[0]);
                    _pendingEntities.RemoveAt(0);
                }

                _timeOutMonitor.AddEntity(entity);
                _pendingEntities.Add(entity);
            }

            // Continue execution chain.
            UpdatePendingExecution();
        }
예제 #4
0
        /// <summary>
        /// This is an entry point for the direct call mechanism. So optimization is on speed and not functionality.
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public override Message ReceiveDirectCall(Message message)
        {
            FastInvokeHelper.FastInvokeHandlerDelegate handler = GetMessageHandler(message);
            if (handler != null)
            {
                return((Message)handler(this, new object[] { message }));
            }
            else
            {// We failed to find a handler for this type or for any of the parent ones.
                TracerHelper.TraceError("Client instance did not handle a request message received, client [" + this.GetType().Name + "], message [" + message.GetType().Name + "].");
                return(null);
            }

            //Message responceMessage = (Message)invokeMethodInfo.Invoke(this, new object[] { message });
            //return responceMessage;
        }
예제 #5
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="messageContainer"></param>
 public void ReceiveMessageContainer(MessageContainer messageContainer)
 {
     TracerHelper.Trace("[" + messageContainer.MessageStreamLength + "], clientCallback[" + OperationContext.Current.SessionId + "]");
     if (MessageContainerReceivedEvent != null)
     {
         string sessionId = OperationContext.Current.SessionId;
         GeneralHelper.FireAndForget(delegate()
         {
             try
             {
                 MessageContainerReceivedEvent(sessionId, messageContainer);
             }
             catch (Exception ex)
             {
                 TracerHelper.TraceError(ex.Message);
             }
         });
     }
 }
예제 #6
0
        /// <summary>
        /// Set operationContextSessionID to "*" to mark all clients.
        /// </summary>
        /// <param name="operationContextSessionID"></param>
        /// <param name="messageContainer"></param>
        public void SendMessageContainer(string operationContextSessionID, MessageContainer messageContainer)
        {
            TracerHelper.TraceEntry("[" + messageContainer.MessageStreamLength + "]");
            if (messageContainer.MessageStreamLength > MaximumAllowedMessageSize)
            {
                TracerHelper.TraceError("Message too bid. Operation failed.");
                return;
                //throw new Exception("Arbiter::MessageContainerTransportServer::MessageContainer requestMessage is too big. Message will not be sent.");
            }

            Dictionary <IMessageContainerTransport, OperationContext> clientsContexts;

            lock (_contextManager)
            {
                clientsContexts = new Dictionary <IMessageContainerTransport, OperationContext>(_contextManager.ClientsContextsUnsafe);
            }

            List <IMessageContainerTransport> badInterfaces = new List <IMessageContainerTransport>();

            foreach (IMessageContainerTransport clientCallback in clientsContexts.Keys)
            {
                // "*" indicates send to all clients
                if (operationContextSessionID == "*" ||
                    clientsContexts[clientCallback].SessionId == operationContextSessionID)
                {
                    try
                    {
                        TracerHelper.Trace("clientCallback [" + operationContextSessionID + "]");
                        clientCallback.ReceiveMessageContainer(messageContainer);
                        TracerHelper.Trace("clientCallback [" + operationContextSessionID + "] invoked");
                    }
                    catch (Exception ex)
                    {
                        TracerHelper.TraceError("Failed to invoke client interface [" + ex.ToString() + "]");
                        badInterfaces.Add(clientCallback);
                    }
                }
            }

            ProcessBadInterfaces(badInterfaces);

            TracerHelper.TraceExit();
        }
예제 #7
0
 /// <summary>
 /// Serializes the message to the internal stream and keeps it there for future usage.
 /// </summary>
 public void SerializeMessage(Message message)
 {
     lock (_messageStream)
     {
         _messageStream.SetLength(0);
         if (message != null)
         {
             try
             {
                 BinaryFormatter formatter = new BinaryFormatter();
                 formatter.Serialize(_messageStream, message);
             }
             catch (Exception exception)
             {
                 TracerHelper.TraceError("Exception in message serialization [" + exception.Message + "].");
                 throw;
             }
         }
     }
 }
        /// <summary>
        /// Send container over to the other side.
        /// </summary>
        /// <param name="messageContainer"></param>
        /// <returns></returns>
        public virtual bool SendMessageContainer(MessageContainer messageContainer)
        {
            TracerHelper.TraceEntry("sending [" + messageContainer.MessageStreamLength + "], sessionID[" + this.ConnectionSessionID + "]");

            SystemMonitor.CheckThrow(messageContainer.MessageStreamLength <= MessageContainerTransportServer.MaximumAllowedMessageSize, "MessageContainer message is too big. Message will not be sent.");
            if (_connectingEvent.WaitOne(_defaultConnectionTimeOut) == false)
            {
                SystemMonitor.OperationError("Failed to send message due to initialization timeout.", TracerItem.PriorityEnum.Medium);
                return(false);
            }

            try
            {
                IMessageContainerTransport messageInterface;
                lock (this)
                {
                    if (_proxyServerInterface == null)
                    {
                        TracerHelper.TraceError("Failed to send to server, interface not created.");
                        return(false);
                    }
                    messageInterface = _proxyServerInterface;
                }

                messageInterface.ReceiveMessageContainer(messageContainer);
                lock (this)
                {
                    _lastServerCall = DateTime.Now;
                }
            }
            catch (Exception exception)
            {
                TracerHelper.TraceError("Failed to send to server, reason [" + exception.Message + "].");
                return(false);
            }

            return(true);
        }
예제 #9
0
        /// <summary>
        /// Handle a request message.
        /// </summary>
        protected virtual void HandleRequestMessage(TransportMessage message)
        {
            FastInvokeHelper.FastInvokeHandlerDelegate handler = GetMessageHandler(message);

            if (handler == null)
            {// We failed to find a handler for this type or for any of the parent ones.
                TracerHelper.TraceError("Client instance did not handle a request message received, client [" + this.GetType().Name + "], message [" + message.GetType().Name + "].");
                return;
            }

            // Before giving the requestMessage to the user class, make a copy of its transport info
            // so that if the user messes it up, we still can deliver the responce properly.
            TransportInfo requestMessageTransportInfo = message.TransportInfo.Clone();

            TransportMessage responseMessage = (TransportMessage)handler(this, new object[] { message });

            if (responseMessage == null)
            {// No result.
                return;
            }

            if (responseMessage is ResponseMessage)
            {
                ((ResponseMessage)responseMessage).RequestMessageTypeName = message.GetType().Name;
            }

            Guid            sessionGuid = requestMessageTransportInfo.CurrentTransportInfo.Value.Id;
            ArbiterClientId?senderID    = requestMessageTransportInfo.CurrentTransportInfo.Value.SenderID;

            requestMessageTransportInfo.PopTransportInfo();

            // Transfer inherited underlaying transport stack.
            responseMessage.TransportInfo = requestMessageTransportInfo;

            // Send the responce requestMessage back.
            DoSendCustom(false, sessionGuid, null, 0, senderID, this.SubscriptionClientID, responseMessage, TimeSpan.Zero);
        }
예제 #10
0
        /// <summary>
        ///
        /// </summary>
        public void ReceiveResponce(TransportMessage message)
        {
            if (message != null &&
                message.GetType() != _responceTypeRequired &&
                message.GetType().IsSubclassOf(_responceTypeRequired) == false)
            {
                SystemMonitor.Error("Session received invalid responce message type [expected (" + _responceTypeRequired.Name + "), received(" + message.GetType().Name + ")]. Message ignored.");
            }
            else
            {
                if (message == null)
                {// We received a NULL signalling to stop wait and abort session.
                    _sessionEndEvent.Set();
                    return;
                }
                else
                {
                    lock (_responcesReceived)
                    {
                        if (_responcesReceived.Count < _responcesRequired)
                        {
                            _responcesReceived.Add(message);

                            if (_responcesReceived.Count == _responcesRequired)
                            {
                                _sessionEndEvent.Set();
                            }
                        }
                        else
                        {// One more requestMessage responce received.
                            TracerHelper.TraceError("Session received too many responce messages. Message ignored.");
                        }
                    }
                }
            }
        }
예제 #11
0
        /// <summary>
        /// Create a message instance based on the information in the internal stream.
        /// </summary>
        public Message CreateMessageInstance()
        {
            lock (_messageStream)
            {
                _messageStream.Position = 0;
                if (_messageStream.Length > 0)
                {
                    try
                    {
                        BinaryFormatter formatter = new BinaryFormatter();
                        Message         message   = (Message)formatter.Deserialize(_messageStream);
                        return(message);
                    }
                    catch (Exception exception)
                    {
                        TracerHelper.TraceError("Exception in message deserialization [" + exception.Message + "].");
                        throw;
                    }
                }
            }

            TracerHelper.TraceError("No message serialized to deserialize.");
            return(null);
        }
예제 #12
0
        /// <summary>
        /// Central sending function.
        /// </summary>
        /// <param name="receiverID">The ID of the receiver module. Can be <b>null</b> and this sends to all in the Arbiter.</param>
        protected TransportMessage[] DoSendCustom(bool isRequest, Guid sessionGuid,
                                                  Type expectedResponseMessageClassType, int responsesRequired,
                                                  ArbiterClientId?receiverId, ArbiterClientId?senderId, TransportMessage message, TimeSpan timeOut)
        {
            //TracerHelper.TraceEntry();

            SessionResults session = null;

            if (receiverId.HasValue && receiverId.Value.IsEmpty /*receiverId.Value.CompareTo(ArbiterClientId.Empty) == 0*/)
            {
                SystemMonitor.Error("Can not send an item to empty receiver. Use null to specify broadcast.");
                return(null);
            }

            // Preliminary verification.
            if (Arbiter == null)
            {
                SystemMonitor.OperationWarning("Using a client [" + this.GetType().Name + ":" + senderId.Value.ClientName + " to " + (receiverId.HasValue ? receiverId.Value.Id.Name : string.Empty) + " , " + message.GetType().Name + "] with no Arbiter assigned.");
                return(null);
            }

            message.IsRequest = isRequest;

            TransportInfoUnit infoUnit = new TransportInfoUnit(sessionGuid, senderId, receiverId);

            message.TransportInfo.AddTransportInfoUnit(infoUnit);

            bool sessionEventResult = false;

            if (expectedResponseMessageClassType != null)
            {// Responce waiting session.
                session = new SessionResults(responsesRequired, expectedResponseMessageClassType);
                lock (_communicationSessions)
                {// Register the session.
                    _communicationSessions.Add(sessionGuid, session);
                }
            }

            SystemMonitor.CheckError(message.TransportInfo.CurrentTransportInfo != null);
            Conversation conversation;

            if (receiverId == null)
            {
                // We shall not use the next level time out mechanism.
                conversation = Arbiter.CreateConversation(senderId.Value, message, TimeSpan.Zero);
            }
            else
            {// Addressed conversation.
                // We shall not use the next level time out mechanism.
                conversation = Arbiter.CreateConversation(senderId.Value, receiverId.Value, message, TimeSpan.Zero);
            }

            if (conversation != null && expectedResponseMessageClassType != null)
            {     // Responce waiting session (only if conversation was properly created).
                if (timeOut == TimeSpan.Zero)
                { // Wait forever.
                    sessionEventResult = session.SessionEndEvent.WaitOne();
                }
                else
                {// Wait given period.
                    sessionEventResult = session.SessionEndEvent.WaitOne(timeOut, false);
                }

                lock (_communicationSessions)
                {// Remote the session.
                    _communicationSessions.Remove(sessionGuid);
                }
            }

            message.TransportInfo.PopTransportInfo();

            if (expectedResponseMessageClassType == null)
            {// No responce waiting, just return.
                //TracerHelper.TraceExit();
                return(null);
            }

            // Responce waiting session.
            if (sessionEventResult == false)
            {// Timed out - only send and receives can time out, as the other ones do not have sessions!!
                TracerHelper.TraceError("Session has timed out [" + message.GetType().Name + "].");
                return(null);
            }

            //TracerHelper.TraceExit();
            return(session.Responses.ToArray());
        }