private void CloseConnection(string clientId, bool notifyFlag)
        {
            using (EneterTrace.Entering())
            {
                try
                {
                    MessageBusMessage aMessage           = new MessageBusMessage(EMessageBusRequest.DisconnectClient, clientId, null);
                    object            aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage);

                    myMessageBusOutputChannel.SendMessage(aSerializedMessage);
                }
                catch (Exception err)
                {
                    EneterTrace.Warning(TracedObject + ErrorHandler.FailedToCloseConnection, err);
                }

                if (notifyFlag)
                {
                    ProtocolMessage aProtocolMessage = new ProtocolMessage(EProtocolMessageType.CloseConnectionRequest, clientId, null);
                    MessageContext  aMessageContext  = new MessageContext(aProtocolMessage, "");

                    NotifyMessageContext(aMessageContext);
                }
            }
        }
        public void StartListening(Action <MessageContext> messageHandler)
        {
            using (EneterTrace.Entering())
            {
                if (messageHandler == null)
                {
                    throw new ArgumentNullException("messageHandler is null.");
                }

                using (ThreadLock.Lock(myListeningManipulatorLock))
                {
                    try
                    {
                        myMessageHandler = messageHandler;
                        myMessageBusOutputChannel.ResponseMessageReceived += OnMessageFromMessageBusReceived;

                        // Open connection with the message bus.
                        myMessageBusOutputChannel.OpenConnection();

                        // Register service in the message bus.
                        MessageBusMessage aMessage           = new MessageBusMessage(EMessageBusRequest.RegisterService, myServiceId, null);
                        object            aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage);

                        myMessageBusOutputChannel.SendMessage(aSerializedMessage);
                    }
                    catch
                    {
                        StopListening();
                        throw;
                    }
                }
            }
        }
        public void SendBroadcast(object message)
        {
            using (EneterTrace.Entering())
            {
                List <string> aDisconnectedClients = new List <string>();

                using (ThreadLock.Lock(myConnectedClients))
                {
                    foreach (string aClientId in myConnectedClients.Keys)
                    {
                        try
                        {
                            MessageBusMessage aMessage           = new MessageBusMessage(EMessageBusRequest.SendResponseMessage, aClientId, message);
                            object            aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage);
                            myMessageBusOutputChannel.SendMessage(aSerializedMessage);
                        }
                        catch (Exception err)
                        {
                            EneterTrace.Error(TracedObject + ErrorHandler.FailedToSendResponseMessage, err);
                            aDisconnectedClients.Add(aClientId);

                            // Note: Exception is not rethrown because if sending to one client fails it should not
                            //       affect sending to other clients.
                        }
                    }
                }

                // Disconnect failed clients.
                foreach (String anOutputConnectorAddress in aDisconnectedClients)
                {
                    CloseConnection(anOutputConnectorAddress, true);
                }
            }
        }
Beispiel #4
0
 public void SendRequestMessage(object message)
 {
     using (EneterTrace.Entering())
     {
         // Note: do not send the client id. It will be automatically assign in the message bus before forwarding the message to the service.
         //       It is done like this due to security reasons. So that some client cannot pretend other client just by sending a different id.
         MessageBusMessage aMessage           = new MessageBusMessage(EMessageBusRequest.SendRequestMessage, "", message);
         object            aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage);
         myMessageBusOutputChannel.SendMessage(aSerializedMessage);
     }
 }
        public void SendResponseMessage(string clientId, object message)
        {
            using (EneterTrace.Entering())
            {
                try
                {
                    MessageBusMessage aMessage           = new MessageBusMessage(EMessageBusRequest.SendResponseMessage, clientId, message);
                    object            aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage);

                    myMessageBusOutputChannel.SendMessage(aSerializedMessage);
                }
                catch
                {
                    CloseConnection(clientId, true);
                    throw;
                }
            }
        }
Beispiel #6
0
        public void OpenConnection(Action <MessageContext> responseMessageHandler)
        {
            using (EneterTrace.Entering())
            {
                if (responseMessageHandler == null)
                {
                    throw new ArgumentNullException("responseMessageHandler is null.");
                }

                using (ThreadLock.Lock(myConnectionManipulatorLock))
                {
                    try
                    {
                        // Open physical connection.
                        myResponseMessageHandler = responseMessageHandler;
                        myMessageBusOutputChannel.ResponseMessageReceived += OnMessageFromMessageBusReceived;
                        myMessageBusOutputChannel.ConnectionClosed        += OnConnectionWithMessageBusClosed;
                        myMessageBusOutputChannel.OpenConnection();

                        myOpenConnectionConfirmed.Reset();

                        // Tell message bus which service shall be associated with this connection.
                        MessageBusMessage aMessage           = new MessageBusMessage(EMessageBusRequest.ConnectClient, myServiceId, null);
                        object            aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage);
                        myMessageBusOutputChannel.SendMessage(aSerializedMessage);

                        if (!myOpenConnectionConfirmed.WaitOne(myOpenConnectionTimeout))
                        {
                            throw new TimeoutException(TracedObject + "failed to open the connection within the timeout: " + myOpenConnectionTimeout);
                        }

                        if (!myMessageBusOutputChannel.IsConnected)
                        {
                            throw new InvalidOperationException(TracedObject + ErrorHandler.FailedToOpenConnection);
                        }
                    }
                    catch
                    {
                        CloseConnection();
                        throw;
                    }
                }
            }
        }
Beispiel #7
0
        public T Deserialize <T>(object serializedData)
        {
            using (EneterTrace.Entering())
            {
                if (serializedData is byte[] == false)
                {
                    throw new ArgumentException("Input parameter 'serializedData' is not byte[].");
                }

                if (typeof(T) != typeof(MessageBusMessage))
                {
                    throw new InvalidOperationException("Data can be deserialized only into" + typeof(MessageBusMessage).Name);
                }

                MessageBusMessage aResult;

                byte[] aData = (byte[])serializedData;

                using (MemoryStream aStream = new MemoryStream(aData))
                {
                    BinaryReader aReader = new BinaryReader(aStream);

                    // Read message bus request.
                    int aRequest = aReader.ReadByte();
                    EMessageBusRequest aMessageBusRequest = (EMessageBusRequest)aRequest;

                    // Read Id
                    string anId = myEncoderDecoder.ReadPlainString(aReader, Encoding.UTF8, myIsLittleEndian);

                    // Read message data.
                    object aMessageData = null;
                    if (aMessageBusRequest == EMessageBusRequest.SendRequestMessage ||
                        aMessageBusRequest == EMessageBusRequest.SendResponseMessage)
                    {
                        aMessageData = myEncoderDecoder.Read(aReader, myIsLittleEndian);
                    }


                    aResult = new MessageBusMessage(aMessageBusRequest, anId, aMessageData);
                    return((T)(object)aResult);
                }
            }
        }
Beispiel #8
0
        public object Serialize <T>(T dataToSerialize)
        {
            using (EneterTrace.Entering())
            {
                if (typeof(T) != typeof(MessageBusMessage))
                {
                    throw new InvalidOperationException("Only " + typeof(MessageBusMessage).Name + " can be serialized.");
                }

                object            aTemp    = dataToSerialize;
                MessageBusMessage aMessage = (MessageBusMessage)aTemp;

                using (MemoryStream aStream = new MemoryStream())
                {
                    BinaryWriter aWriter = new BinaryWriter(aStream);

                    // Write messagebus request.
                    byte aRequestType = (byte)aMessage.Request;
                    aWriter.Write((byte)aRequestType);

                    // Write Id.
                    myEncoderDecoder.WritePlainString(aWriter, aMessage.Id, Encoding.UTF8, myIsLittleEndian);

                    // Write message data.
                    if (aMessage.Request == EMessageBusRequest.SendRequestMessage ||
                        aMessage.Request == EMessageBusRequest.SendResponseMessage)
                    {
                        if (aMessage.MessageData == null)
                        {
                            throw new InvalidOperationException("Message data is null.");
                        }

                        myEncoderDecoder.Write(aWriter, aMessage.MessageData, myIsLittleEndian);
                    }

                    return(aStream.ToArray());
                }
            }
        }
        private void OnMessageFromMessageBusReceived(object sender, DuplexChannelMessageEventArgs e)
        {
            using (EneterTrace.Entering())
            {
                MessageBusMessage aMessageBusMessage;
                try
                {
                    aMessageBusMessage = mySerializer.Deserialize <MessageBusMessage>(e.Message);
                }
                catch (Exception err)
                {
                    EneterTrace.Error(TracedObject + "failed to deserialize message.", err);
                    return;
                }

                if (aMessageBusMessage.Request == EMessageBusRequest.ConnectClient)
                {
                    MessageBusMessage aResponseMessage    = new MessageBusMessage(EMessageBusRequest.ConfirmClient, aMessageBusMessage.Id, null);
                    object            aSerializedResponse = mySerializer.Serialize <MessageBusMessage>(aResponseMessage);
                    myMessageBusOutputChannel.SendMessage(aSerializedResponse);

                    ProtocolMessage aProtocolMessage = new ProtocolMessage(EProtocolMessageType.OpenConnectionRequest, aMessageBusMessage.Id, null);
                    MessageContext  aMessageContext  = new MessageContext(aProtocolMessage, e.SenderAddress);

                    IThreadDispatcher aDispatcher = myThreadDispatcherProvider.GetDispatcher();
                    using (ThreadLock.Lock(myConnectedClients))
                    {
                        myConnectedClients[aProtocolMessage.ResponseReceiverId] = aDispatcher;
                    }

                    aDispatcher.Invoke(() => NotifyMessageContext(aMessageContext));
                }
                else if (aMessageBusMessage.Request == EMessageBusRequest.DisconnectClient)
                {
                    ProtocolMessage aProtocolMessage = new ProtocolMessage(EProtocolMessageType.CloseConnectionRequest, aMessageBusMessage.Id, aMessageBusMessage.MessageData);
                    MessageContext  aMessageContext  = new MessageContext(aProtocolMessage, e.SenderAddress);

                    IThreadDispatcher aDispatcher;
                    using (ThreadLock.Lock(myConnectedClients))
                    {
                        myConnectedClients.TryGetValue(aProtocolMessage.ResponseReceiverId, out aDispatcher);
                        if (aDispatcher != null)
                        {
                            myConnectedClients.Remove(aProtocolMessage.ResponseReceiverId);
                        }
                        else
                        {
                            aDispatcher = myThreadDispatcherProvider.GetDispatcher();
                        }
                    }

                    aDispatcher.Invoke(() => NotifyMessageContext(aMessageContext));
                }
                else if (aMessageBusMessage.Request == EMessageBusRequest.SendRequestMessage)
                {
                    ProtocolMessage aProtocolMessage = new ProtocolMessage(EProtocolMessageType.MessageReceived, aMessageBusMessage.Id, aMessageBusMessage.MessageData);
                    MessageContext  aMessageContext  = new MessageContext(aProtocolMessage, e.SenderAddress);

                    IThreadDispatcher aDispatcher;
                    using (ThreadLock.Lock(myConnectedClients))
                    {
                        myConnectedClients.TryGetValue(aProtocolMessage.ResponseReceiverId, out aDispatcher);
                        if (aDispatcher == null)
                        {
                            aDispatcher = myThreadDispatcherProvider.GetDispatcher();
                            myConnectedClients[aProtocolMessage.ResponseReceiverId] = aDispatcher;
                        }
                    }

                    aDispatcher.Invoke(() => NotifyMessageContext(aMessageContext));
                }
            }
        }
Beispiel #10
0
        private void ForwardMessageToService(string clientResponseReceiverId, MessageBusMessage messageFromClient)
        {
            using (EneterTrace.Entering())
            {
                TClientContext aClientContext = null;
                using (ThreadLock.Lock(myConnectionLock))
                {
                    aClientContext = myConnectedClients.FirstOrDefault(x => x.ClientResponseReceiverId == clientResponseReceiverId);
                }

                if (aClientContext != null)
                {
                    // Forward the incoming message to the service.
                    IDuplexInputChannel anInputChannel = myServiceConnector.AttachedDuplexInputChannel;
                    if (anInputChannel != null)
                    {
                        aClientContext.ForwardToServiceThreadDispatcher.Invoke(
                            () =>
                        {
                            using (EneterTrace.Entering())
                            {
                                try
                                {
                                    // Add the client id into the message.
                                    // Note: Because of security reasons we do not expect Ids from the client but using Ids associated with the connection session.
                                    //       Otherwise it would be possible that some client could use id of another client to pretend a different client.
                                    messageFromClient.Id      = clientResponseReceiverId;
                                    object aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(messageFromClient);

                                    anInputChannel.SendResponseMessage(aClientContext.ServiceResponseReceiverId, aSerializedMessage);

                                    if (MessageToServiceSent != null)
                                    {
                                        MessageBusMessageEventArgs anEventArgs = new MessageBusMessageEventArgs(aClientContext.ServiceId, aClientContext.ServiceResponseReceiverId, clientResponseReceiverId, messageFromClient.MessageData);
                                        try
                                        {
                                            MessageToServiceSent(this, anEventArgs);
                                        }
                                        catch (Exception err)
                                        {
                                            EneterTrace.Warning(TracedObject + ErrorHandler.DetectedException, err);
                                        }
                                    }
                                }
                                catch (Exception err)
                                {
                                    string anErrorMessage = TracedObject + "failed to send message to the service '" + aClientContext.ServiceId + "'.";
                                    EneterTrace.Error(anErrorMessage, err);

                                    UnregisterService(aClientContext.ServiceResponseReceiverId);
                                }
                            }
                        });
                    }
                }
                else
                {
                    string anErrorMessage = TracedObject + "failed to send message to the service because the client was not found.";
                    EneterTrace.Warning(anErrorMessage);
                }
            }
        }
Beispiel #11
0
        private void UnregisterClient(string clientResponseReceiverId, bool sendCloseConnectionToServiceFlag, bool disconnectClientFlag)
        {
            using (EneterTrace.Entering())
            {
                // Unregistering client.
                TClientContext aClientContext = null;
                using (ThreadLock.Lock(myConnectionLock))
                {
                    myConnectedClients.RemoveWhere(x =>
                    {
                        if (x.ClientResponseReceiverId == clientResponseReceiverId)
                        {
                            aClientContext = x;
                            return(true);
                        }

                        return(false);
                    });
                }

                if (aClientContext != null)
                {
                    if (sendCloseConnectionToServiceFlag)
                    {
                        try
                        {
                            // Send close connection message to the service.
                            MessageBusMessage aMessage           = new MessageBusMessage(EMessageBusRequest.DisconnectClient, aClientContext.ClientResponseReceiverId, null);
                            object            aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage);

                            IDuplexInputChannel anInputChannel = myServiceConnector.AttachedDuplexInputChannel;
                            if (anInputChannel != null)
                            {
                                anInputChannel.SendResponseMessage(aClientContext.ServiceResponseReceiverId, aSerializedMessage);
                            }
                        }
                        catch (Exception err)
                        {
                            string anErrorMessage = TracedObject + ErrorHandler.FailedToCloseConnection;
                            EneterTrace.Warning(anErrorMessage, err);
                        }
                    }

                    // Disconnecting the client.
                    if (disconnectClientFlag)
                    {
                        IDuplexInputChannel anInputChannel1 = myClientConnector.AttachedDuplexInputChannel;
                        if (anInputChannel1 != null)
                        {
                            anInputChannel1.DisconnectResponseReceiver(aClientContext.ClientResponseReceiverId);
                        }
                    }

                    if (ClientDisconnected != null)
                    {
                        MessageBusClientEventArgs anEventArgs = new MessageBusClientEventArgs(aClientContext.ServiceId, aClientContext.ServiceResponseReceiverId, clientResponseReceiverId);
                        try
                        {
                            ClientDisconnected(this, anEventArgs);
                        }
                        catch (Exception err)
                        {
                            EneterTrace.Warning(TracedObject + ErrorHandler.DetectedException, err);
                        }
                    }
                }
            }
        }
Beispiel #12
0
        private void RegisterClient(string clientResponseReceiverId, string serviceId)
        {
            using (EneterTrace.Entering())
            {
                bool           anIsNewClientConnected = false;
                TClientContext aClientContext         = null;
                using (ThreadLock.Lock(myConnectionLock))
                {
                    aClientContext = myConnectedClients.FirstOrDefault(x => x.ClientResponseReceiverId == clientResponseReceiverId);

                    // If such client does not exist yet then create it.
                    if (aClientContext == null)
                    {
                        TServiceContext aServiceContext = myConnectedServices.FirstOrDefault(x => x.ServiceId == serviceId);

                        // If requested service exists.
                        if (aServiceContext != null)
                        {
                            aClientContext = new TClientContext(clientResponseReceiverId, serviceId, aServiceContext.ServiceResponseReceiverId);
                            myConnectedClients.Add(aClientContext);
                            anIsNewClientConnected = true;
                        }
                    }
                }

                if (anIsNewClientConnected)
                {
                    // Send open connection message to the service.
                    try
                    {
                        MessageBusMessage aMessage           = new MessageBusMessage(EMessageBusRequest.ConnectClient, clientResponseReceiverId, null);
                        object            aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage);

                        IDuplexInputChannel anInputChannel = myServiceConnector.AttachedDuplexInputChannel;
                        if (anInputChannel != null)
                        {
                            anInputChannel.SendResponseMessage(aClientContext.ServiceResponseReceiverId, aSerializedMessage);
                        }
                    }
                    catch (Exception err)
                    {
                        EneterTrace.Warning(TracedObject + "failed to send open connection message to the service '" + aClientContext.ServiceId + "'.", err);

                        // Note: The service should not be disconnected from the message bus when not available.
                        //       Because it can be "just" overloaded. So only this new client will be disconnected from the message bus.
                        UnregisterClient(clientResponseReceiverId, false, true);
                    }
                }
                else
                {
                    if (aClientContext != null)
                    {
                        EneterTrace.Warning(TracedObject + "failed to connect the client already exists. The connection will be closed.");
                        UnregisterClient(clientResponseReceiverId, false, true);
                    }
                    else
                    {
                        EneterTrace.Warning(TracedObject + "failed to connec the client because the service '" + serviceId + "' does not exist. The connection will be closed.");
                        UnregisterClient(clientResponseReceiverId, false, true);
                    }
                }
            }
        }