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); } } }
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); } }
// 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); } } }
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; } }
public void Invoke(Action workItem) { using (EneterTrace.Entering()) { EneterTrace.Debug(myDispatcherTraceMessage); myWorkingThreadDispatcher.BeginInvoke(workItem); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } } } } }
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); } }
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); } }
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); } }
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); } } }
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); } } }
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); } }
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); } } } }
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(); } }
// 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."); } } }
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); } }
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()); } }
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); } } }
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); } }
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); } } }
// 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(); } } }