Пример #1
0
        public virtual void Duplex_09_StopListening()
        {
            ClientMockFarm aClients = new ClientMockFarm(MessagingSystemFactory, ChannelId, 3);
            ServiceMock    aService = new ServiceMock(MessagingSystemFactory, ChannelId);

            try
            {
                aService.InputChannel.StartListening();

                aClients.OpenConnectionsAsync();
                Assert.IsTrue(aClients.Clients[0].OutputChannel.IsConnected);
                Assert.IsTrue(aClients.Clients[1].OutputChannel.IsConnected);
                Assert.IsTrue(aClients.Clients[2].OutputChannel.IsConnected);

                aClients.WaitUntilAllConnectionsAreOpen(1000);
                aService.WaitUntilResponseReceiversConnectNotified(3, 1000);

                aService.InputChannel.StopListening();
                Assert.IsFalse(aService.InputChannel.IsListening);

                //aService.WaitUntilAllResponseReceiversDisconnectNotified(1000);
                aClients.WaitUntilAllConnectionsAreClosed(1000);
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClients.CloseAllConnections();
                aService.InputChannel.StopListening();

                // Wait for traces.
                Thread.Sleep(100);
            }
        }
        // Note: This method is called from the message receiving thread.
        private void HandleMessage(MessageContext messageContext)
        {
            using (EneterTrace.Entering())
            {
                if (messageContext.ProtocolMessage.MessageType == EProtocolMessageType.MessageReceived)
                {
                    EneterTrace.Debug("REQUEST MESSAGE RECEIVED");

                    myDispatchingAfterMessageReading.Invoke(() =>
                    {
                        Dispatcher.Invoke(() => NotifyMessageReceived(messageContext, messageContext.ProtocolMessage));
                    });
                }
                else if (messageContext.ProtocolMessage.MessageType == EProtocolMessageType.OpenConnectionRequest)
                {
                    EneterTrace.Debug("CLIENT CONNECTION RECEIVED");
                    myDispatchingAfterMessageReading.Invoke(() =>
                    {
                        Dispatcher.Invoke(() => Notify(ResponseReceiverConnected, messageContext.ProtocolMessage.ResponseReceiverId, messageContext.SenderAddress));
                    });
                }
                else if (messageContext.ProtocolMessage.MessageType == EProtocolMessageType.CloseConnectionRequest)
                {
                    EneterTrace.Debug("CLIENT DISCONNECTION RECEIVED");
                    myDispatchingAfterMessageReading.Invoke(() =>
                    {
                        Dispatcher.Invoke(() => Notify(ResponseReceiverDisconnected, messageContext.ProtocolMessage.ResponseReceiverId, messageContext.SenderAddress));
                    });
                }
                else
                {
                    EneterTrace.Warning(TracedObject + ErrorHandler.FailedToReceiveMessageBecauseIncorrectFormat);
                }
            }
        }
Пример #3
0
        public virtual void Duplex_10_DisconnectResponseReceiver()
        {
            ClientMock  aClient  = new ClientMock(MessagingSystemFactory, ChannelId);
            ServiceMock aService = new ServiceMock(MessagingSystemFactory, ChannelId);

            try
            {
                aService.InputChannel.StartListening();

                aClient.OutputChannel.OpenConnection();

                aService.WaitUntilResponseReceiversConnectNotified(1, 1000);
                aClient.WaitUntilConnectionOpenIsNotified(1000);
                //string aConnectedResponseReceiverId = aService.ConnectedResponseReceivers[0].ResponseReceiverId;

                aService.InputChannel.DisconnectResponseReceiver(aService.ConnectedResponseReceivers.First().ResponseReceiverId);

                aClient.WaitUntilConnectionClosedIsNotified(1000);
                //aService.WaitUntilAllResponseReceiversDisconnectNotified(1000);

                //Assert.AreEqual(aConnectedResponseReceiverId, aService.DisconnectedResponseReceivers[0].ResponseReceiverId);
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClient.OutputChannel.CloseConnection();
                aService.InputChannel.StopListening();

                // Wait for traces.
                Thread.Sleep(100);
            }
        }
Пример #4
0
        // A message from the client was received.
        private void OnMessageFromClientReceived(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 from service. The service will be disconnected.", err);
                    UnregisterClient(e.ResponseReceiverId, true, true);
                    return;
                }

                if (aMessageBusMessage.Request == EMessageBusRequest.ConnectClient)
                {
                    EneterTrace.Debug("CLIENT OPENS CONNECTION TO '" + aMessageBusMessage.Id + "'.");
                    RegisterClient(e.ResponseReceiverId, aMessageBusMessage.Id);
                }
                else if (aMessageBusMessage.Request == EMessageBusRequest.SendRequestMessage)
                {
                    ForwardMessageToService(e.ResponseReceiverId, aMessageBusMessage);
                }
            }
        }
Пример #5
0
        public void FilterTest()
        {
            EneterTrace.DetailLevel = EneterTrace.EDetailLevel.Debug;

            // Write traces to the string.
            EneterTrace.TraceLog = new StringWriter();

            try
            {
                // Eneter trace.
                EneterTrace.NameSpaceFilter = new Regex("^Eneter");
                EneterTrace.Debug("This message shall be traced.");
                Thread.Sleep(500);
                string aMessage = EneterTrace.TraceLog.ToString();
                Assert.IsTrue(aMessage.Contains("This message shall be traced."));


                // Create the new "log".
                EneterTrace.TraceLog = new StringWriter();

                // Eneter trace shall be filtered out.
                EneterTrace.NameSpaceFilter = new Regex(@"^(?!\bEneter\b)");
                EneterTrace.Debug("This message shall not be traced.");
                Thread.Sleep(500);
                Assert.AreEqual("", EneterTrace.TraceLog.ToString());
            }
            finally
            {
                EneterTrace.TraceLog        = null;
                EneterTrace.NameSpaceFilter = null;
                EneterTrace.DetailLevel     = EneterTrace.EDetailLevel.Short;
            }
        }
Пример #6
0
 public void Invoke(Action workItem)
 {
     using (EneterTrace.Entering())
     {
         EneterTrace.Debug(myDispatcherTraceMessage);
         myWorkingThreadDispatcher.BeginInvoke(workItem);
     }
 }
Пример #7
0
        public virtual void Duplex_06_OpenCloseConnection()
        {
            ClientMock  aClient  = new ClientMock(MessagingSystemFactory, ChannelId);
            ServiceMock aService = new ServiceMock(MessagingSystemFactory, ChannelId);

            try
            {
                aService.InputChannel.StartListening();

                // Open the connection.
                aClient.OutputChannel.OpenConnection();
                Assert.IsTrue(aClient.OutputChannel.IsConnected);

                // handling open connection on the client side.
                EneterTrace.Info("1");
                aClient.WaitUntilConnectionOpenIsNotified(1000);
                Assert.AreEqual(aClient.OutputChannel.ChannelId, aClient.NotifiedOpenConnection.ChannelId);
                Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aClient.NotifiedOpenConnection.ResponseReceiverId);

                // handling open connection on the service side.
                EneterTrace.Info("2");
                aService.WaitUntilResponseReceiversConnectNotified(1, 1000);
                Assert.AreEqual(1, aService.ConnectedResponseReceivers.Count());
                if (CompareResponseReceiverId)
                {
                    Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aService.ConnectedResponseReceivers[0].ResponseReceiverId);
                }

                aClient.OutputChannel.CloseConnection();
                Assert.IsFalse(aClient.OutputChannel.IsConnected);

                EneterTrace.Info("3");
                //aClient.WaitUntilConnectionClosedIsNotified(1000);
                //Assert.AreEqual(aClient.OutputChannel.ChannelId, aClient.NotifiedCloseConnection.ChannelId);
                //Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aClient.NotifiedCloseConnection.ResponseReceiverId);

                EneterTrace.Info("4");
                aService.WaitUntilAllResponseReceiversDisconnectNotified(1000);
                Assert.AreEqual(1, aService.DisconnectedResponseReceivers.Count());
                if (CompareResponseReceiverId)
                {
                    Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aService.DisconnectedResponseReceivers.First().ResponseReceiverId);
                }
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClient.OutputChannel.CloseConnection();
                aService.InputChannel.StopListening();

                // Wait for traces.
                Thread.Sleep(100);
            }
        }
Пример #8
0
        private void SendOfflineBroadcastResponseMessage(string channelId, object broadcastMessage,
                                                         int numberOfClients, int numberOfMessages,
                                                         int openConnectionTimeout,
                                                         int allMessagesReceivedTimeout)
        {
            ThreadPool.SetMinThreads(50, 2);

            ClientMockFarm aClientFarm = new ClientMockFarm(MessagingSystem, channelId, numberOfClients);
            ServiceMock    aService    = new ServiceMock(MessagingSystem, channelId);

            try
            {
                aService.InputChannel.StartListening();

                // Send broadcasts.
                for (int i = 0; i < numberOfMessages; ++i)
                {
                    aService.InputChannel.SendResponseMessage("*", broadcastMessage);
                }

                Thread.Sleep(500);

                aClientFarm.OpenConnectionsAsync();

                aClientFarm.WaitUntilAllConnectionsAreOpen(openConnectionTimeout);
                aService.WaitUntilResponseReceiversConnectNotified(numberOfClients, openConnectionTimeout);
                Assert.AreEqual(aClientFarm.Clients.Count(), aService.ConnectedResponseReceivers.Count());
                foreach (ClientMock aClient in aClientFarm.Clients)
                {
                    Assert.IsTrue(aService.ConnectedResponseReceivers.Any(x => x.ResponseReceiverId == aClient.OutputChannel.ResponseReceiverId));
                }

                PerformanceTimer aStopWatch = new PerformanceTimer();
                aStopWatch.Start();

                aClientFarm.WaitUntilAllResponsesAreReceived(numberOfMessages, allMessagesReceivedTimeout);

                aStopWatch.Stop();

                foreach (DuplexChannelMessageEventArgs aResponseMessage in aClientFarm.ReceivedResponses)
                {
                    Assert.AreEqual(broadcastMessage, aResponseMessage.Message);
                }
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClientFarm.CloseAllConnections();
                aService.InputChannel.StopListening();

                //EneterTrace.StopProfiler();
                Thread.Sleep(500);
            }
        }
Пример #9
0
        private double calculateRange(double from, double to)
        {
            using (EneterTrace.Entering())
            {
                // Calculate pi
                double aResult = 0.0;
                double aDx     = 0.00001;
                for (double x = from; x < to; x += aDx)
                {
                    EneterTrace.Debug("blblblblblblblblblblblblbbllblbblblblblbl");
                    aResult += 2 * Math.Sqrt(1 - x * x) * aDx;
                }

                return(aResult);
            }
        }
Пример #10
0
        public virtual void Duplex_11_CloseConnection()
        {
            ClientMockFarm aClients = new ClientMockFarm(MessagingSystemFactory, ChannelId, 2);
            ServiceMock    aService = new ServiceMock(MessagingSystemFactory, ChannelId);

            try
            {
                aService.InputChannel.StartListening();

                aClients.OpenConnectionsAsync();
                Assert.IsTrue(aClients.Clients[0].OutputChannel.IsConnected);
                Assert.IsTrue(aClients.Clients[1].OutputChannel.IsConnected);

                aClients.WaitUntilAllConnectionsAreOpen(1000);
                aService.WaitUntilResponseReceiversConnectNotified(2, 1000);
                string aResponseReceiverId1 = aService.ConnectedResponseReceivers[0].ResponseReceiverId;

                // Cient 1 closes the connection.
                aClients.Clients[0].OutputChannel.CloseConnection();
                Assert.IsFalse(aClients.Clients[0].OutputChannel.IsConnected);

                //aClients.Clients[0].WaitUntilConnectionClosedIsNotified(1000);
                aService.WaitUntilResponseRecieverIdDisconnectNotified(aResponseReceiverId1, 2000);
                if (CompareResponseReceiverId)
                {
                    Assert.AreEqual(aClients.Clients[0].OutputChannel.ResponseReceiverId, aService.DisconnectedResponseReceivers[0].ResponseReceiverId);
                }

                // Client 2 can send message.
                aClients.Clients[1].OutputChannel.SendMessage(myRequestMessage);

                aService.WaitUntilMessagesAreReceived(1, 1000);

                Assert.AreEqual(myRequestMessage, aService.ReceivedMessages[0].Message);
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClients.CloseAllConnections();
                aService.InputChannel.StopListening();

                // Wait for traces.
                Thread.Sleep(100);
            }
        }
Пример #11
0
        public virtual void Duplex_12_CloseFromConnectionOpened()
        {
            ClientMock aClient = new ClientMock(MessagingSystemFactory, ChannelId);

            aClient.DoOnConnectionOpen((x, y) =>
            {
                if (MessagingSystemFactory is NamedPipeMessagingSystemFactory)
                {
                    Thread.Sleep(500);
                }

                aClient.OutputChannel.CloseConnection();
            });

            ServiceMock aService = new ServiceMock(MessagingSystemFactory, ChannelId);

            try
            {
                aService.InputChannel.StartListening();

                aClient.OutputChannel.OpenConnection();

                aClient.WaitUntilConnectionOpenIsNotified(1000);

                if (MessagingSystemFactory is SynchronousMessagingSystemFactory == false)
                {
                    aService.WaitUntilResponseReceiversConnectNotified(1, 5000);
                }

                // Client is disconnected.
                //aClient.WaitUntilConnectionClosedIsNotified(1000);

                // Client should be disconnected from the event handler.
                aService.WaitUntilAllResponseReceiversDisconnectNotified(2000);
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClient.OutputChannel.CloseConnection();
                aService.InputChannel.StopListening();

                // Wait for traces.
                Thread.Sleep(100);
            }
        }
Пример #12
0
        public void A13_TimeoutedResponseReceiver()
        {
            ClientMock  aClient  = new ClientMock(MessagingSystem, ChannelId);
            ServiceMock aService = new ServiceMock(MessagingSystem, ChannelId);

            try
            {
                aService.InputChannel.StartListening();

                // Open the connection.
                aClient.OutputChannel.OpenConnection();
                Assert.IsTrue(aClient.OutputChannel.IsConnected);

                // handling open connection on the client side.
                EneterTrace.Info("1");
                aClient.WaitUntilConnectionOpenIsNotified(2000);
                Assert.AreEqual(aClient.OutputChannel.ChannelId, aClient.NotifiedOpenConnection.ChannelId);
                Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aClient.NotifiedOpenConnection.ResponseReceiverId);

                // handling open connection on the service side.
                EneterTrace.Info("2");
                aService.WaitUntilResponseReceiversConnectNotified(1, 1000);
                Assert.AreEqual(1, aService.ConnectedResponseReceivers.Count());
                Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aService.ConnectedResponseReceivers[0].ResponseReceiverId);

                aClient.OutputChannel.CloseConnection();
                Assert.IsFalse(aClient.OutputChannel.IsConnected);

                // Service will disconnect the response receiver when the offline timout is exceeded.
                EneterTrace.Info("3");
                aService.WaitUntilAllResponseReceiversDisconnectNotified(2000);
                Assert.AreEqual(1, aService.DisconnectedResponseReceivers.Count());
                Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aService.DisconnectedResponseReceivers.First().ResponseReceiverId);
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClient.OutputChannel.CloseConnection();
                aService.InputChannel.StopListening();

                // Wait for traces.
                Thread.Sleep(100);
            }
        }
Пример #13
0
            private void OnMessageReceived(object sender, TypedRequestReceivedEventArgs <Interval> e)
            {
                using (EneterTrace.Entering())
                {
                    EneterTrace.Debug(string.Format("Address: {0} From: {1} To: {2}",
                                                    myRequestReceiver.AttachedDuplexInputChannel.ChannelId,
                                                    e.RequestMessage.From, e.RequestMessage.To));

                    double aResult = 0.0;
                    double aDx     = 0.000000001;
                    for (double x = e.RequestMessage.From; x < e.RequestMessage.To; x += aDx)
                    {
                        aResult += 2 * Math.Sqrt(1 - x * x) * aDx;
                    }

                    myRequestReceiver.SendResponseMessage(e.ResponseReceiverId, aResult);
                }
            }
Пример #14
0
        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.ConfirmClient)
                {
                    // Indicate the connection is open and relase the waiting in the OpenConnection().
                    myOpenConnectionConfirmed.Set();

                    EneterTrace.Debug("CONNECTION CONFIRMED");
                }
                else if (aMessageBusMessage.Request == EMessageBusRequest.SendResponseMessage)
                {
                    Action <MessageContext> aResponseHandler = myResponseMessageHandler;

                    if (aResponseHandler != null)
                    {
                        ProtocolMessage aProtocolMessage = new ProtocolMessage(EProtocolMessageType.MessageReceived, myServiceId, aMessageBusMessage.MessageData);
                        MessageContext  aMessageContext  = new MessageContext(aProtocolMessage, e.SenderAddress);

                        try
                        {
                            aResponseHandler(aMessageContext);
                        }
                        catch (Exception err)
                        {
                            EneterTrace.Warning(TracedObject + ErrorHandler.DetectedException, err);
                        }
                    }
                }
            }
        }
Пример #15
0
        public virtual void Duplex_09_StopListening_SendMessage()
        {
            ClientMock  aClient  = new ClientMock(MessagingSystemFactory, ChannelId);
            ServiceMock aService = new ServiceMock(MessagingSystemFactory, ChannelId);

            try
            {
                aService.InputChannel.StartListening();

                aClient.OutputChannel.OpenConnection();

                aService.WaitUntilResponseReceiversConnectNotified(1, 1000);

                aService.InputChannel.StopListening();
                Assert.IsFalse(aService.InputChannel.IsListening);

                bool isSomeException = false;
                try
                {
                    // Try to send a message via the duplex output channel.
                    aClient.OutputChannel.SendMessage(myRequestMessage);
                }
                catch
                {
                    // Because the duplex input channel is not listening the sending must
                    // fail with an exception. The type of the exception depends from the type of messaging system.
                    isSomeException = true;
                }

                Assert.IsTrue(isSomeException);
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClient.OutputChannel.CloseConnection();
                aService.InputChannel.StopListening();

                // Wait for traces.
                Thread.Sleep(100);
            }
        }
Пример #16
0
        public void Execute(Action job)
        {
            using (ThreadLock.Lock(myJobQueue))
            {
                if (!myIsWorkingThreadRunning)
                {
                    myIsWorkingThreadRunning = true;
                    EneterThreadPool.QueueUserWorkItem(DoJobs);

                    // If we are tracing then wait until the message about the working thread is ready.
                    if (EneterTrace.DetailLevel == EneterTrace.EDetailLevel.Debug)
                    {
                        myTraceMessageReady.WaitOne();
                    }
                }

                // Trace into which thread it forwards the job.
                EneterTrace.Debug(myInvokeTraceMessage);

                myJobQueue.Enqueue(job);
            }
        }
Пример #17
0
        public virtual void Duplex_13_DisconnectFromResponseReceiverConnected()
        {
            ClientMock  aClient  = new ClientMock(MessagingSystemFactory, ChannelId);
            ServiceMock aService = new ServiceMock(MessagingSystemFactory, ChannelId);

            aService.DoOnResponseReceiverConnected((x, y) =>
            {
                if (MessagingSystemFactory is SynchronousMessagingSystemFactory == false)
                {
                    aClient.WaitUntilConnectionOpenIsNotified(1000);
                }

                aService.InputChannel.DisconnectResponseReceiver(y.ResponseReceiverId);
            });

            try
            {
                aService.InputChannel.StartListening();

                // The ecent will try to close connection.
                aClient.OutputChannel.OpenConnection();

                aClient.WaitUntilConnectionOpenIsNotified(1000);

                //aService.WaitUntilAllResponseReceiversDisconnectNotified(1000);

                aClient.WaitUntilConnectionClosedIsNotified(1000);
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClient.OutputChannel.CloseConnection();
                aService.InputChannel.StopListening();

                // Wait for traces.
                Thread.Sleep(100);
            }
        }
Пример #18
0
 private void HandleResponse(MessageContext messageContext)
 {
     using (EneterTrace.Entering())
     {
         if (messageContext == null ||
             messageContext.ProtocolMessage == null ||
             messageContext.ProtocolMessage.MessageType == EProtocolMessageType.CloseConnectionRequest)
         {
             EneterTrace.Debug("CLIENT DISCONNECTED RECEIVED");
             myDispatchingAfterResponseReading.Invoke(() => CleanAfterConnection(false, true));
         }
         else if (messageContext.ProtocolMessage.MessageType == EProtocolMessageType.MessageReceived)
         {
             EneterTrace.Debug("RESPONSE MESSAGE RECEIVED");
             myDispatchingAfterResponseReading.Invoke(() => Dispatcher.Invoke(() => NotifyResponseMessageReceived(messageContext.ProtocolMessage.Message, messageContext.SenderAddress)));
         }
         else
         {
             EneterTrace.Warning(TracedObject + ErrorHandler.FailedToReceiveMessageBecauseIncorrectFormat);
         }
     }
 }
Пример #19
0
        private void OnMessageFromServiceReceived(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 from service. The service will be disconnected.", err);
                    UnregisterService(e.ResponseReceiverId);
                    return;
                }

                if (aMessageBusMessage.Request == EMessageBusRequest.RegisterService)
                {
                    EneterTrace.Debug("REGISTER SERVICE: " + aMessageBusMessage.Id);
                    RegisterService(aMessageBusMessage.Id, e.ResponseReceiverId);
                }
                else if (aMessageBusMessage.Request == EMessageBusRequest.SendResponseMessage)
                {
                    // Note: forward the same message - it does not have to be serialized again.
                    ForwardMessageToClient(aMessageBusMessage.Id, e.ResponseReceiverId, e.Message, aMessageBusMessage.MessageData);
                }
                else if (aMessageBusMessage.Request == EMessageBusRequest.DisconnectClient)
                {
                    EneterTrace.Debug("SERVICE DISCONNECTS CLIENT");
                    UnregisterClient(aMessageBusMessage.Id, false, true);
                }
                else if (aMessageBusMessage.Request == EMessageBusRequest.ConfirmClient)
                {
                    EneterTrace.Debug("SERVICE CONFIRMS CLIENT");
                    ForwardMessageToClient(aMessageBusMessage.Id, e.ResponseReceiverId, e.Message, null);
                }
            }
        }
Пример #20
0
        public virtual void Duplex_08_OpenFromConnectionClosed()
        {
            ClientMock aClient = new ClientMock(MessagingSystemFactory, ChannelId);

            bool anIsConnected = false;

            aClient.DoOnConnectionClosed((x, y) =>
            {
                EneterTrace.Debug("DoOnConnectionClosed");

                anIsConnected = aClient.OutputChannel.IsConnected;

                if (MessagingSystemFactory is SharedMemoryMessagingSystemFactory)
                {
                    Thread.Sleep(300);
                }

                aClient.OutputChannel.OpenConnection();
            });

            ServiceMock aService = new ServiceMock(MessagingSystemFactory, ChannelId);

            try
            {
                aService.InputChannel.StartListening();

                // Client opens the connection.
                aClient.OutputChannel.OpenConnection();

                aClient.WaitUntilConnectionOpenIsNotified(1000);
                Assert.IsFalse(anIsConnected);

                aService.WaitUntilResponseReceiversConnectNotified(1, 1000);
                string aConnectedResponseReceiverId = aService.ConnectedResponseReceivers[0].ResponseReceiverId;

                aClient.ClearTestResults();
                aService.ClearTestResults();

                // Service disconnects the client.
                aService.InputChannel.DisconnectResponseReceiver(aConnectedResponseReceiverId);

                //aService.WaitUntilResponseRecieverIdDisconnectNotified(aConnectedResponseReceiverId, 1000);
                aClient.WaitUntilConnectionClosedIsNotified(3000);
                //Assert.AreEqual(aConnectedResponseReceiverId, aService.DisconnectedResponseReceivers[0].ResponseReceiverId);

                // Client should open the connection again.
                aClient.WaitUntilConnectionOpenIsNotified(1000);

                if (MessagingSystemFactory is SynchronousMessagingSystemFactory == false)
                {
                    aService.WaitUntilResponseReceiversConnectNotified(1, 1000);
                }
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClient.OutputChannel.CloseConnection();
                aService.InputChannel.StopListening();

                // Wait for traces.
                Thread.Sleep(500);
            }
        }
Пример #21
0
        private void UnregisterService(string serviceResponseReceiverId)
        {
            using (EneterTrace.Entering())
            {
                List <string> aClientsToDisconnect = new List <string>();

                string aServiceId = null;
                using (ThreadLock.Lock(myConnectionLock))
                {
                    // Remove the service.
                    myConnectedServices.RemoveWhere(x =>
                    {
                        if (x.ServiceResponseReceiverId == serviceResponseReceiverId)
                        {
                            aServiceId = x.ServiceId;
                            return(true);
                        }

                        return(false);
                    });

                    // Remove all clients connected to the service.
                    myConnectedClients.RemoveWhere(x =>
                    {
                        if (x.ServiceResponseReceiverId == serviceResponseReceiverId)
                        {
                            aClientsToDisconnect.Add(x.ClientResponseReceiverId);

                            // Indicate the item shall be removed.
                            return(true);
                        }

                        return(false);
                    });
                }

                // Close connections with clients.
                if (myClientConnector.IsDuplexInputChannelAttached)
                {
                    foreach (string aClientResponseReceiverId in aClientsToDisconnect)
                    {
                        IDuplexInputChannel anInputChannel = myClientConnector.AttachedDuplexInputChannel;
                        if (anInputChannel != null)
                        {
                            anInputChannel.DisconnectResponseReceiver(aClientResponseReceiverId);
                        }
                    }
                }

                IDuplexInputChannel anInputChannel2 = myServiceConnector.AttachedDuplexInputChannel;
                if (anInputChannel2 != null)
                {
                    anInputChannel2.DisconnectResponseReceiver(serviceResponseReceiverId);
                }

                if (ServiceUnregistered != null && !string.IsNullOrEmpty(aServiceId))
                {
                    EneterTrace.Debug("SERVICE '" + aServiceId + "' UNREGISTERED");

                    try
                    {
                        MessageBusServiceEventArgs anEvent = new MessageBusServiceEventArgs(aServiceId, serviceResponseReceiverId);
                        ServiceUnregistered(this, anEvent);
                    }
                    catch (Exception err)
                    {
                        EneterTrace.Error(TracedObject + ErrorHandler.DetectedException, err);
                    }
                }
            }
        }
Пример #22
0
        public void A17_Online_Offline_Events()
        {
            // Duplex output channel without queue - it will not try to reconnect.
            IBufferedDuplexOutputChannel aDuplexOutputChannel = (IBufferedDuplexOutputChannel)MessagingSystem.CreateDuplexOutputChannel(ChannelId);
            IBufferedDuplexInputChannel  aDuplexInputChannel  = (IBufferedDuplexInputChannel)MessagingSystem.CreateDuplexInputChannel(ChannelId);

            AutoResetEvent aConnectionsCompletedEvent = new AutoResetEvent(false);

            aDuplexInputChannel.ResponseReceiverConnected += (x, y) =>
            {
                aConnectionsCompletedEvent.Set();
            };

            AutoResetEvent aResponseReceiverOnline = new AutoResetEvent(false);

            aDuplexInputChannel.ResponseReceiverOnline += (x, y) =>
            {
                aResponseReceiverOnline.Set();
            };

            AutoResetEvent aResponseReceiverOffline = new AutoResetEvent(false);

            aDuplexInputChannel.ResponseReceiverOffline += (x, y) =>
            {
                aResponseReceiverOffline.Set();
            };

            AutoResetEvent aOnlineIsRaised         = new AutoResetEvent(false);
            bool           aOnlineStateAfterOnline = false;

            aDuplexOutputChannel.ConnectionOnline += (x, y) =>
            {
                aOnlineStateAfterOnline = aDuplexOutputChannel.IsOnline;
                EneterTrace.Debug(aOnlineStateAfterOnline.ToString());
                aOnlineIsRaised.Set();
            };

            AutoResetEvent aOfflineIsRaised         = new AutoResetEvent(false);
            bool           aOnlineStateAfterOffline = false;

            aDuplexOutputChannel.ConnectionOffline += (x, y) =>
            {
                aOnlineStateAfterOffline = aDuplexOutputChannel.IsOnline;
                aOfflineIsRaised.Set();
            };

            try
            {
                aDuplexOutputChannel.OpenConnection();

                if (!aOfflineIsRaised.WaitOne(2000))
                {
                    Assert.Fail("Offline event was not raised.");
                }
                Assert.IsFalse(aOnlineStateAfterOffline);

                // start listening
                aDuplexInputChannel.StartListening();

                if (!aOnlineIsRaised.WaitOne(2000))
                {
                    Assert.Fail("Online event was not raised.");
                }
                Assert.IsTrue(aOnlineStateAfterOnline);

                if (!aResponseReceiverOnline.WaitOne(2000))
                {
                    Assert.Fail("ResponseReceiverOnline event was not raised.");
                }

                // Wait until the connection is open.
                if (!aConnectionsCompletedEvent.WaitOne(2000))
                {
                    Assert.Fail("Connection was not open.");
                }

                // Disconnect the response receiver.
                aDuplexInputChannel.DisconnectResponseReceiver(aDuplexOutputChannel.ResponseReceiverId);

                if (!aOfflineIsRaised.WaitOne(2000))
                {
                    Assert.Fail("Offline event was not raised after disconnection.");
                }
                Assert.IsFalse(aOnlineStateAfterOffline);

                if (aResponseReceiverOffline.WaitOne(500))
                {
                    Assert.Fail("ResponseReceiverOffline event shall NOT be raised if DisconnectResponseReceiver was called.");
                }


                // The duplex output channel will try to connect again, therefore wait until connected.
                aConnectionsCompletedEvent.WaitOne();


                if (!aOnlineIsRaised.WaitOne(2000))
                {
                    Assert.Fail("Online event was not raised after reconnection.");
                }
                Assert.IsTrue(aOnlineStateAfterOnline);

                if (!aResponseReceiverOnline.WaitOne(2000))
                {
                    Assert.Fail("ResponseReceiverOnline event was not raised.");
                }

                // duplex output channel closes the connection.
                aDuplexOutputChannel.CloseConnection();


                if (!aResponseReceiverOffline.WaitOne(2000))
                {
                    Assert.Fail("ResponseReceiverOffline event was not raised.");
                }

                if (aOfflineIsRaised.WaitOne(500))
                {
                    Assert.Fail("Offline event shall NOT be raised after CloseConnection().");
                }
                Assert.IsFalse(aOnlineStateAfterOffline);
            }
            finally
            {
                aDuplexOutputChannel.CloseConnection();
                aDuplexInputChannel.StopListening();
            }
        }
Пример #23
0
        // This method is called when a message from the service is received.
        // This can be either the response for a request or it can be an event raised in the service.
        protected override void OnResponseMessageReceived(object sender, DuplexChannelMessageEventArgs e)
        {
            using (EneterTrace.Entering())
            {
                RpcMessage aMessage = null;
                try
                {
                    aMessage = mySerializer.ForResponseReceiver(e.ResponseReceiverId).Deserialize <RpcMessage>(e.Message);
                }
                catch (Exception err)
                {
                    EneterTrace.Error(TracedObject + "failed to deserialize incoming message.", err);
                    return;
                }

                // If it is a response for a call.
                if (aMessage.Request == ERpcRequest.Response)
                {
                    EneterTrace.Debug("RETURN FROM RPC RECEIVED");

                    // Try to find if there is a pending request waiting for the response.
                    RemoteCallContext anRpcContext;
                    using (ThreadLock.Lock(myPendingRemoteCalls))
                    {
                        myPendingRemoteCalls.TryGetValue(aMessage.Id, out anRpcContext);
                    }

                    if (anRpcContext != null)
                    {
                        if (string.IsNullOrEmpty(aMessage.ErrorType))
                        {
                            anRpcContext.SerializedReturnValue = aMessage.SerializedReturn;
                        }
                        else
                        {
                            RpcException anException = new RpcException(aMessage.ErrorMessage, aMessage.ErrorType, aMessage.ErrorDetails);
                            anRpcContext.Error = anException;
                        }

                        // Release the pending request.
                        anRpcContext.RpcCompleted.Set();
                    }
                }
                else if (aMessage.Request == ERpcRequest.RaiseEvent)
                {
                    EneterTrace.Debug("EVENT FROM SERVICE RECEIVED");

                    if (aMessage.SerializedParams != null && aMessage.SerializedParams.Length > 0)
                    {
                        // Try to raise an event.
                        // The event is raised in its own thread so that the receiving thread is not blocked.
                        // Note: raising an event cannot block handling of response messages because it can block
                        //       processing of an RPC response for which the RPC caller thread is waiting.
                        //       And if this waiting caller thread is a thread where events are routed and if the routing
                        //       of these events is 'blocking' then a deadlock can occur.
                        //       Therefore ThreadPool is used.
                        EneterThreadPool.QueueUserWorkItem(() => myThreadDispatcher.Invoke(() => RaiseEvent(aMessage.OperationName, aMessage.SerializedParams[0])));
                    }
                    else
                    {
                        // Note: this happens if the event is of type EventErgs.
                        // The event is raised in its own thread so that the receiving thread is not blocked.
                        EneterThreadPool.QueueUserWorkItem(() => myThreadDispatcher.Invoke(() => RaiseEvent(aMessage.OperationName, null)));
                    }
                }
                else
                {
                    EneterTrace.Warning(TracedObject + "detected a message with unknown flag number.");
                }
            }
        }
Пример #24
0
        private void SendMessageReceiveResponse(string channelId, object message, object responseMessage,
                                                int numberOfClients, int numberOfMessages,
                                                int openConnectionTimeout,
                                                int allMessagesReceivedTimeout)
        {
            ThreadPool.SetMinThreads(100, 2);

            ClientMockFarm aClientFarm = new ClientMockFarm(MessagingSystemFactory, channelId, numberOfClients);

            ServiceMock aService = new ServiceMock(MessagingSystemFactory, channelId);

            aService.DoOnMessageReceived_SendResponse(responseMessage);

            try
            {
                //EneterTrace.StartProfiler();

                aService.InputChannel.StartListening();
                aClientFarm.OpenConnectionsAsync();

                aClientFarm.WaitUntilAllConnectionsAreOpen(openConnectionTimeout);
                aService.WaitUntilResponseReceiversConnectNotified(numberOfClients, openConnectionTimeout);
                Assert.AreEqual(aClientFarm.Clients.Count(), aService.ConnectedResponseReceivers.Count());

                if (CompareResponseReceiverId)
                {
                    foreach (ClientMock aClient in aClientFarm.Clients)
                    {
                        Assert.IsTrue(aService.ConnectedResponseReceivers.Any(x => x.ResponseReceiverId == aClient.OutputChannel.ResponseReceiverId));
                    }
                }

                PerformanceTimer aStopWatch = new PerformanceTimer();
                aStopWatch.Start();

                aClientFarm.SendMessageAsync(message, numberOfMessages);
                aClientFarm.WaitUntilAllResponsesAreReceived(numberOfMessages, allMessagesReceivedTimeout);

                aStopWatch.Stop();

                // Wait little bit more for case there is an error that more messages are sent.
                Thread.Sleep(500);

                Assert.AreEqual(numberOfMessages * numberOfClients, aService.ReceivedMessages.Count());
                Assert.AreEqual(numberOfMessages * numberOfClients, aClientFarm.ReceivedResponses.Count());
                foreach (DuplexChannelMessageEventArgs aMessage in aService.ReceivedMessages)
                {
                    Assert.AreEqual(message, aMessage.Message);
                }
                foreach (DuplexChannelMessageEventArgs aResponseMessage in aClientFarm.ReceivedResponses)
                {
                    Assert.AreEqual(responseMessage, aResponseMessage.Message);
                }
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClientFarm.CloseAllConnections();
                aService.InputChannel.StopListening();

                //EneterTrace.StopProfiler();
                Thread.Sleep(200);
            }
        }
Пример #25
0
        public void CalculatePi()
        {
            //EneterTrace.DetailLevel = EneterTrace.EDetailLevel.Debug;
            //EneterTrace.TraceLog = new StreamWriter("d:/tracefile.txt");

            IMessagingSystemFactory aThreadMessaging = new ThreadMessagingSystemFactory();

            List <CalculatorService> aServices = new List <CalculatorService>();

            ILoadBalancer aDistributor = null;
            IDuplexTypedMessageSender <double, Interval> aSender = null;

            // Create 50 calculating services.
            try
            {
                for (int i = 0; i < 50; ++i)
                {
                    aServices.Add(new CalculatorService("a" + i.ToString(), aThreadMessaging));
                }

                // Create Distributor
                ILoadBalancerFactory aDistributorFactory = new RoundRobinBalancerFactory(aThreadMessaging);
                aDistributor = aDistributorFactory.CreateLoadBalancer();

                // Attach available services to the distributor.
                for (int i = 0; i < aServices.Count; ++i)
                {
                    aDistributor.AddDuplexOutputChannel("a" + i.ToString());
                }

                // Attach input channel to the distributor.
                IDuplexInputChannel anInputChannel = aThreadMessaging.CreateDuplexInputChannel("DistributorAddress");
                aDistributor.AttachDuplexInputChannel(anInputChannel);


                // Create client that needs to calculate PI.
                IDuplexTypedMessagesFactory aTypedMessagesFactory = new DuplexTypedMessagesFactory();
                aSender = aTypedMessagesFactory.CreateDuplexTypedMessageSender <double, Interval>();

                AutoResetEvent aCalculationCompletedEvent = new AutoResetEvent(false);
                int            aCount = 0;
                double         aPi    = 0.0;
                aSender.ResponseReceived += (x, y) =>
                {
                    ++aCount;
                    EneterTrace.Debug("Completed interval: " + aCount.ToString());

                    aPi += y.ResponseMessage;

                    if (aCount == 400)
                    {
                        aCalculationCompletedEvent.Set();
                    }
                };

                IDuplexOutputChannel anOutputChannel = aThreadMessaging.CreateDuplexOutputChannel("DistributorAddress");
                aSender.AttachDuplexOutputChannel(anOutputChannel);

                // Sender sends several parallel requests to calculate specified intervals.
                // 2 / 0.005 = 400 intervals.
                for (double i = -1.0; i <= 1.0; i += 0.005)
                {
                    Interval anInterval = new Interval(i, i + 0.005);
                    aSender.SendRequestMessage(anInterval);
                }

                // Wait until all requests are calculated.
                EneterTrace.Debug("Test waits until completion.");
                aCalculationCompletedEvent.WaitOne();

                EneterTrace.Info("Calculated PI = " + aPi.ToString());
            }
            catch (Exception err)
            {
                EneterTrace.Error("Test failed", err);
                throw;
            }
            finally
            {
                aSender.DetachDuplexOutputChannel();
                aDistributor.DetachDuplexInputChannel();
                aServices.ForEach(x => x.Dispose());
            }
        }
Пример #26
0
        private void OnMessageReceived(object sender, DuplexChannelMessageEventArgs e)
        {
            using (EneterTrace.Entering())
            {
                // If the connection has already been authenticated then this is a regular request message that will be notified.
                bool anIsAuthenticated;
                using (ThreadLock.Lock(myAuthenticatedConnections))
                {
                    anIsAuthenticated = myAuthenticatedConnections.Contains(e.ResponseReceiverId);
                }
                if (anIsAuthenticated)
                {
                    Notify <DuplexChannelMessageEventArgs>(MessageReceived, e, true);
                    return;
                }


                bool aDisconnectFlag = true;
                bool aNewResponseReceiverAuthenticated = false;

                TNotYetAuthenticatedConnection aConnection;
                using (ThreadLock.Lock(myNotYetAuthenticatedConnections))
                {
                    myNotYetAuthenticatedConnections.TryGetValue(e.ResponseReceiverId, out aConnection);
                    if (aConnection == null)
                    {
                        aConnection = new TNotYetAuthenticatedConnection();
                        myNotYetAuthenticatedConnections[e.ResponseReceiverId] = aConnection;
                    }
                }

                if (aConnection.HandshakeMessage == null)
                {
                    EneterTrace.Debug("LOGIN RECEIVED");

                    // If the connection is in the state that it is not logged in then this must be the login message.
                    // The handshake message will be sent.
                    try
                    {
                        aConnection.LoginMessage     = e.Message;
                        aConnection.HandshakeMessage = myGetHandshakeMessageCallback(e.ChannelId, e.ResponseReceiverId, e.Message);

                        // If the login was accepted.
                        if (aConnection.HandshakeMessage != null)
                        {
                            try
                            {
                                // Send the handshake message to the client.
                                myUnderlayingInputChannel.SendResponseMessage(e.ResponseReceiverId, aConnection.HandshakeMessage);
                                aDisconnectFlag = false;
                            }
                            catch (Exception err)
                            {
                                string anErrorMessage = TracedObject + "failed to send the handshake message. The client will be disconnected.";
                                EneterTrace.Error(anErrorMessage, err);
                            }
                        }
                        else
                        {
                            // the client will be disconnected.
                        }
                    }
                    catch (Exception err)
                    {
                        string anErrorMessage = TracedObject + "failed to get the handshake message. The client will be disconnected.";
                        EneterTrace.Error(anErrorMessage, err);
                    }
                }
                // If the connection is in the state that the handshake message was sent then this is the handshake response message.
                // The response for the handshake will be verified.
                else
                {
                    EneterTrace.Debug("HANDSHAKE RESPONSE RECEIVED");

                    try
                    {
                        if (myAuthenticateCallback(e.ChannelId, e.ResponseReceiverId, aConnection.LoginMessage, aConnection.HandshakeMessage, e.Message))
                        {
                            // Send acknowledge message that the connection is authenticated.
                            try
                            {
                                myUnderlayingInputChannel.SendResponseMessage(e.ResponseReceiverId, "OK");

                                aDisconnectFlag = false;
                                aNewResponseReceiverAuthenticated = true;

                                // Move the connection from not-yet-authenticated to authenticated connections.
                                using (ThreadLock.Lock(myAuthenticatedConnections))
                                {
                                    myAuthenticatedConnections.Add(e.ResponseReceiverId);
                                }
                                using (ThreadLock.Lock(myNotYetAuthenticatedConnections))
                                {
                                    myNotYetAuthenticatedConnections.Remove(e.ResponseReceiverId);
                                }
                            }
                            catch (Exception err)
                            {
                                string anErrorMessage = TracedObject + "failed to send the acknowledge message that the connection was authenticated. The client will be disconnected.";
                                EneterTrace.Error(anErrorMessage, err);
                            }
                        }
                    }
                    catch (Exception err)
                    {
                        string anErrorMessage = TracedObject + "failed to verify the response for the handshake message. The client will be disconnected.";
                        EneterTrace.Error(anErrorMessage, err);
                    }
                }


                // If the connection with the client shall be closed.
                if (aDisconnectFlag)
                {
                    using (ThreadLock.Lock(myNotYetAuthenticatedConnections))
                    {
                        myNotYetAuthenticatedConnections.Remove(e.ResponseReceiverId);
                    }

                    try
                    {
                        myUnderlayingInputChannel.DisconnectResponseReceiver(e.ResponseReceiverId);
                    }
                    catch (Exception err)
                    {
                        string anErrorMessage = TracedObject + "failed to disconnect response receiver.";
                        EneterTrace.Warning(anErrorMessage, err);
                    }
                }

                // Notify ResponseReceiverConnected if a new connection is authenticated.
                // Note: the notification runs outside the lock in order to reduce blocking.
                if (aNewResponseReceiverAuthenticated)
                {
                    ResponseReceiverEventArgs anEventArgs = new ResponseReceiverEventArgs(e.ResponseReceiverId, e.SenderAddress);
                    Notify <ResponseReceiverEventArgs>(ResponseReceiverConnected, anEventArgs, false);
                }
            }
        }
Пример #27
0
        public virtual void Duplex_06_OpenCloseOpenSend()
        {
            ClientMock  aClient  = new ClientMock(MessagingSystemFactory, ChannelId);
            ServiceMock aService = new ServiceMock(MessagingSystemFactory, ChannelId);

            aService.DoOnMessageReceived_SendResponse(myResponseMessage);

            try
            {
                aService.InputChannel.StartListening();

                // Client opens the connection.
                aClient.OutputChannel.OpenConnection();
                Assert.IsTrue(aClient.OutputChannel.IsConnected);

                aClient.WaitUntilConnectionOpenIsNotified(1000);
                Assert.AreEqual(aClient.OutputChannel.ChannelId, aClient.NotifiedOpenConnection.ChannelId);
                Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aClient.NotifiedOpenConnection.ResponseReceiverId);

                aService.WaitUntilResponseReceiversConnectNotified(1, 1000);
                Assert.AreEqual(1, aService.ConnectedResponseReceivers.Count());
                if (CompareResponseReceiverId)
                {
                    Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aService.ConnectedResponseReceivers[0].ResponseReceiverId);
                }

                // Client closes the connection.
                aClient.OutputChannel.CloseConnection();
                Assert.IsFalse(aClient.OutputChannel.IsConnected);

                //aClient.WaitUntilConnectionClosedIsNotified(1000);
                //Assert.AreEqual(aClient.OutputChannel.ChannelId, aClient.NotifiedCloseConnection.ChannelId);
                //Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aClient.NotifiedCloseConnection.ResponseReceiverId);

                aService.WaitUntilAllResponseReceiversDisconnectNotified(3000);
                Assert.AreEqual(1, aService.DisconnectedResponseReceivers.Count());
                if (CompareResponseReceiverId)
                {
                    Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aService.DisconnectedResponseReceivers[0].ResponseReceiverId);
                }

                aClient.ClearTestResults();
                aService.ClearTestResults();


                // Client opens the connection 2nd time.
                aClient.OutputChannel.OpenConnection();
                Assert.IsTrue(aClient.OutputChannel.IsConnected);

                aClient.WaitUntilConnectionOpenIsNotified(1000);
                Assert.AreEqual(aClient.OutputChannel.ChannelId, aClient.NotifiedOpenConnection.ChannelId);
                Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aClient.NotifiedOpenConnection.ResponseReceiverId);

                aService.WaitUntilResponseReceiversConnectNotified(1, 1000);
                Assert.AreEqual(1, aService.ConnectedResponseReceivers.Count());
                if (CompareResponseReceiverId)
                {
                    Assert.AreEqual(aClient.OutputChannel.ResponseReceiverId, aService.ConnectedResponseReceivers[0].ResponseReceiverId);
                }

                // Client sends the message.
                aClient.OutputChannel.SendMessage(myRequestMessage);

                aClient.WaitUntilResponseMessagesAreReceived(1, 1000);

                Assert.AreEqual(myRequestMessage, aService.ReceivedMessages.First().Message);
                Assert.AreEqual(myResponseMessage, aClient.ReceivedMessages.First().Message);
            }
            finally
            {
                EneterTrace.Debug("CLEANING AFTER TEST");

                aClient.OutputChannel.CloseConnection();
                aService.InputChannel.StopListening();

                // Wait for traces.
                Thread.Sleep(100);
            }
        }
        public void DoRequestListening()
        {
            using (EneterTrace.Entering())
            {
                myIsListeningToResponses = true;
                ushort aCloseCode = 0;

                try
                {
                    DynamicStream aContinuousMessageStream = null;

                    while (!myStopReceivingRequestedFlag)
                    {
                        // Decode the incoming message.
                        WebSocketFrame aFrame = WebSocketFormatter.DecodeFrame(myClientStream);

                        if (!myStopReceivingRequestedFlag && aFrame != null)
                        {
                            // Frames from server must be unmasked.
                            // According the protocol, If the frame was NOT masked, the server must close connection with the client.
                            if (aFrame.MaskFlag == false)
                            {
                                throw new InvalidOperationException(TracedObject + "received unmasked frame from the client. Frames from client shall be masked.");
                            }

                            // Process the frame.
                            if (aFrame.FrameType == EFrameType.Ping)
                            {
                                // Response 'pong'. The response responses same data as received in the 'ping'.
                                SendFrame(maskingKey => WebSocketFormatter.EncodePongFrame(maskingKey, aFrame.Message));
                            }
                            else if (aFrame.FrameType == EFrameType.Close)
                            {
                                EneterTrace.Debug(TracedObject + "received the close frame.");
                                break;
                            }
                            else if (aFrame.FrameType == EFrameType.Pong)
                            {
                                Notify(PongReceived);
                            }
                            // If a new message starts.
                            else if (aFrame.FrameType == EFrameType.Binary || aFrame.FrameType == EFrameType.Text)
                            {
                                // If a previous message is not finished then the new message is not expected -> protocol error.
                                if (aContinuousMessageStream != null)
                                {
                                    EneterTrace.Warning(TracedObject + "detected unexpected new message. (previous message was not finished)");

                                    // Protocol error close code.
                                    aCloseCode = 1002;
                                    break;
                                }

                                WebSocketMessage aReceivedMessage = null;

                                // If the message does not come in multiple frames then optimize the performance
                                // and use MemoryStream instead of DynamicStream.
                                if (aFrame.IsFinal)
                                {
                                    MemoryStream aMessageStream = new MemoryStream(aFrame.Message);
                                    aReceivedMessage = new WebSocketMessage(aFrame.FrameType == EFrameType.Text, aMessageStream);
                                }
                                else
                                // if the message is split to several frames then use DynamicStream so that writing of incoming
                                // frames and reading of already received data can run in parallel.
                                {
                                    // Create stream where the message data will be writen.
                                    aContinuousMessageStream = new DynamicStream();
                                    aContinuousMessageStream.WriteWithoutCopying(aFrame.Message, 0, aFrame.Message.Length);
                                    aReceivedMessage = new WebSocketMessage(aFrame.FrameType == EFrameType.Text, aContinuousMessageStream);
                                }

                                // Put received message to the queue.
                                myReceivedMessages.EnqueueMessage(aReceivedMessage);
                            }
                            // If a message continues. (I.e. message is split into more fragments.)
                            else if (aFrame.FrameType == EFrameType.Continuation)
                            {
                                // If the message does not exist then continuing frame does not have any sense -> protocol error.
                                if (aContinuousMessageStream == null)
                                {
                                    EneterTrace.Warning(TracedObject + "detected unexpected continuing of a message. (none message was started before)");

                                    // Protocol error close code.
                                    aCloseCode = 1002;
                                    break;
                                }

                                aContinuousMessageStream.WriteWithoutCopying(aFrame.Message, 0, aFrame.Message.Length);

                                // If this is the final frame.
                                if (aFrame.IsFinal)
                                {
                                    aContinuousMessageStream.IsBlockingMode = false;
                                    aContinuousMessageStream = null;
                                }
                            }
                        }

                        // If disconnected
                        if (aFrame == null)// || !myTcpClient.Client.Poll(0, SelectMode.SelectWrite))
                        {
                            //EneterTrace.Warning(TracedObject + "detected the TCP connection is not available. The connection will be closed.");
                            break;
                        }
                    }
                }
                catch (IOException)
                {
                    // Ignore this exception. It is often thrown when the connection was closed.
                    // Do not thrace this because the tracing degradates the performance in this case.
                }
                catch (Exception err)
                {
                    EneterTrace.Error(TracedObject + ErrorHandler.FailedInListeningLoop, err);
                }

                // If the connection is being closed due to a protocol error.
                if (aCloseCode > 1000)
                {
                    // Try to send the close message.
                    try
                    {
                        byte[] aCloseMessage = WebSocketFormatter.EncodeCloseFrame(null, aCloseCode);
                        myClientStream.Write(aCloseMessage, 0, aCloseMessage.Length);
                    }
                    catch
                    {
                    }
                }

                myIsListeningToResponses = false;

                myReceivedMessages.UnblockProcessingThreads();

                // Notify the listening to messages stoped.
                Notify(ConnectionClosed);
            }
        }
Пример #29
0
        public void ProcessRemoteRequest(DuplexChannelMessageEventArgs e)
        {
            using (EneterTrace.Entering())
            {
                ISerializer aSerializer = mySerializer.ForResponseReceiver(e.ResponseReceiverId);

                // Deserialize the incoming message.
                RpcMessage aRequestMessage = null;
                try
                {
                    aRequestMessage = aSerializer.Deserialize <RpcMessage>(e.Message);
                }
                catch (Exception err)
                {
                    EneterTrace.Error(TracedObject + "failed to deserialize incoming request message.", err);
                    return;
                }

                RpcMessage aResponseMessage = new RpcMessage()
                {
                    Id      = aRequestMessage.Id,
                    Request = ERpcRequest.Response
                };

                // If it is a remote call of a method/function.
                if (aRequestMessage.Request == ERpcRequest.InvokeMethod)
                {
                    EneterTrace.Debug("RPC RECEIVED");

                    // Get the method from the service that shall be invoked.
                    ServiceMethod aServiceMethod;
                    myServiceMethods.TryGetValue(aRequestMessage.OperationName, out aServiceMethod);
                    if (aServiceMethod != null)
                    {
                        if (aRequestMessage.SerializedParams != null && aRequestMessage.SerializedParams.Length == aServiceMethod.InputParameterTypes.Length)
                        {
                            // Deserialize input parameters.
                            object[] aDeserializedInputParameters = new object[aServiceMethod.InputParameterTypes.Length];
                            try
                            {
                                for (int i = 0; i < aServiceMethod.InputParameterTypes.Length; ++i)
                                {
                                    aDeserializedInputParameters[i] = aSerializer.Deserialize(aServiceMethod.InputParameterTypes[i], aRequestMessage.SerializedParams[i]);
                                }
                            }
                            catch (Exception err)
                            {
                                string anErrorMessage = "failed to deserialize input parameters for '" + aRequestMessage.OperationName + "'.";
                                EneterTrace.Error(anErrorMessage, err);

                                aResponseMessage.ErrorType    = err.GetType().Name;
                                aResponseMessage.ErrorMessage = anErrorMessage;
                                aResponseMessage.ErrorDetails = err.ToString();
                            }

                            if (string.IsNullOrEmpty(aResponseMessage.ErrorType))
                            {
                                object aResult = null;
                                try
                                {
                                    // Invoke the service method.
                                    aResult = aServiceMethod.Method.Invoke(myService, aDeserializedInputParameters);
                                }
                                catch (Exception err)
                                {
                                    // Note: Use InnerException to skip the wrapping ReflexionException.
                                    Exception ex = (err.InnerException != null) ? err.InnerException : err;

                                    EneterTrace.Error(TracedObject + ErrorHandler.DetectedException, ex);

                                    // The exception will be responded to the client.
                                    aResponseMessage.ErrorType    = ex.GetType().Name;
                                    aResponseMessage.ErrorMessage = ex.Message;
                                    aResponseMessage.ErrorDetails = ex.ToString();
                                }

                                if (string.IsNullOrEmpty(aResponseMessage.ErrorType))
                                {
                                    try
                                    {
                                        // Serialize the result.
                                        if (aServiceMethod.Method.ReturnType != typeof(void))
                                        {
                                            aResponseMessage.SerializedReturn = aSerializer.Serialize(aServiceMethod.Method.ReturnType, aResult);
                                        }
                                        else
                                        {
                                            aResponseMessage.SerializedReturn = null;
                                        }
                                    }
                                    catch (Exception err)
                                    {
                                        string anErrorMessage = TracedObject + "failed to serialize the result.";
                                        EneterTrace.Error(anErrorMessage, err);

                                        aResponseMessage.ErrorType    = err.GetType().Name;
                                        aResponseMessage.ErrorMessage = anErrorMessage;
                                        aResponseMessage.ErrorDetails = err.ToString();
                                    }
                                }
                            }
                        }
                        else
                        {
                            aResponseMessage.ErrorType    = typeof(InvalidOperationException).Name;
                            aResponseMessage.ErrorMessage = TracedObject + "failed to process '" + aRequestMessage.OperationName + "' because it has incorrect number of input parameters.";
                            EneterTrace.Error(aResponseMessage.ErrorMessage);
                        }
                    }
                    else
                    {
                        aResponseMessage.ErrorType    = typeof(InvalidOperationException).Name;
                        aResponseMessage.ErrorMessage = "Method '" + aRequestMessage.OperationName + "' does not exist in the service.";
                        EneterTrace.Error(aResponseMessage.ErrorMessage);
                    }
                }
                // If it is a request to subscribe/unsubcribe an event.
                else if (aRequestMessage.Request == ERpcRequest.SubscribeEvent || aRequestMessage.Request == ERpcRequest.UnsubscribeEvent)
                {
                    EventContext anEventContext = null;
                    using (ThreadLock.Lock(myServiceEvents))
                    {
                        anEventContext = myServiceEvents.FirstOrDefault(x => x.EventInfo.Name == aRequestMessage.OperationName);
                        if (anEventContext != null)
                        {
                            if (aRequestMessage.Request == ERpcRequest.SubscribeEvent)
                            {
                                EneterTrace.Debug("SUBSCRIBE REMOTE EVENT RECEIVED");

                                // Note: Events are added to the HashSet.
                                //       Therefore it is ensured each client is subscribed only once.
                                anEventContext.SubscribedClients.Add(e.ResponseReceiverId);
                            }
                            else
                            {
                                EneterTrace.Debug("UNSUBSCRIBE REMOTE EVENT RECEIVED");

                                anEventContext.SubscribedClients.Remove(e.ResponseReceiverId);
                            }
                        }
                    }

                    if (anEventContext == null)
                    {
                        aResponseMessage.ErrorType    = typeof(InvalidOperationException).Name;
                        aResponseMessage.ErrorMessage = TracedObject + "Event '" + aRequestMessage.OperationName + "' does not exist in the service.";
                        EneterTrace.Error(aResponseMessage.ErrorMessage);
                    }
                }
                else
                {
                    aResponseMessage.ErrorType    = typeof(InvalidOperationException).Name;
                    aResponseMessage.ErrorMessage = TracedObject + "could not recognize the incoming request. If it is RPC, Subscribing or Unsubscribfing.";
                    EneterTrace.Error(aResponseMessage.ErrorMessage);
                }


                try
                {
                    // Serialize the response message.
                    object aSerializedResponse = aSerializer.Serialize <RpcMessage>(aResponseMessage);
                    myInputChannel.SendResponseMessage(e.ResponseReceiverId, aSerializedResponse);
                }
                catch (Exception err)
                {
                    EneterTrace.Error(TracedObject + "." + aRequestMessage.OperationName + " " + ErrorHandler.FailedToSendResponseMessage, err);
                }
            }
        }
Пример #30
0
        // Note: This method is called in the thread defined in used ThreadDispatcher.
        //       So it is the "correct" thread.
        private void OnResponseMessageReceived(object sender, DuplexChannelMessageEventArgs e)
        {
            using (EneterTrace.Entering())
            {
                if (myIsConnectionAcknowledged)
                {
                    // If the connection is properly established via handshaking.
                    myThreadDispatcher.Invoke(() => Notify <DuplexChannelMessageEventArgs>(ResponseMessageReceived, e, true));
                    return;
                }

                bool aCloseConnectionFlag = false;

                // This is the handshake message.
                if (!myIsHandshakeResponseSent)
                {
                    EneterTrace.Debug("HANDSHAKE RECEIVED");

                    // Get the response for the handshake message.
                    object aHandshakeResponseMessage = null;
                    try
                    {
                        aHandshakeResponseMessage = myGetHandshakeResponseMessageCallback(e.ChannelId, e.ResponseReceiverId, e.Message);
                        aCloseConnectionFlag      = (aHandshakeResponseMessage == null);
                    }
                    catch (Exception err)
                    {
                        string anErrorMessage = TracedObject + "failed to get the handshake response message. The connection will be closed.";
                        EneterTrace.Warning(anErrorMessage, err);

                        aCloseConnectionFlag = true;
                    }

                    // Send back the response for the handshake.
                    if (!aCloseConnectionFlag)
                    {
                        try
                        {
                            // Note: keep setting this flag before sending. Otherwise synchronous messaging will not work!
                            myIsHandshakeResponseSent = true;
                            myUnderlyingOutputChannel.SendMessage(aHandshakeResponseMessage);
                        }
                        catch (Exception err)
                        {
                            myIsHandshakeResponseSent = false;

                            string anErrorMessage = TracedObject + "failed to send the handshake response message. The connection will be closed.";
                            EneterTrace.Error(anErrorMessage, err);

                            aCloseConnectionFlag = true;
                        }
                    }
                }
                else
                {
                    EneterTrace.Debug("CONNECTION ACKNOWLEDGE RECEIVED");

                    // If the handshake was sent then this message must be acknowledgement.
                    string anAcknowledgeMessage = e.Message as string;

                    // If the acknowledge message is wrong then disconnect.
                    if (String.IsNullOrEmpty(anAcknowledgeMessage) || anAcknowledgeMessage != "OK")
                    {
                        string anErrorMessage = TracedObject + "detected incorrect acknowledge message. The connection will be closed.";
                        EneterTrace.Error(anErrorMessage);

                        aCloseConnectionFlag = true;
                    }
                    else
                    {
                        myIsConnectionAcknowledged = true;
                        myAuthenticationEnded.Set();

                        // Notify the connection is open.
                        DuplexChannelEventArgs anEventArgs = new DuplexChannelEventArgs(ChannelId, ResponseReceiverId, e.SenderAddress);
                        myThreadDispatcher.Invoke(() => Notify <DuplexChannelEventArgs>(ConnectionOpened, anEventArgs, false));
                    }
                }

                if (aCloseConnectionFlag)
                {
                    myUnderlyingOutputChannel.CloseConnection();

                    // Release the waiting in OpenConnection(..).
                    myAuthenticationEnded.Set();
                }
            }
        }