private void CloseConnection(string clientId, bool notifyFlag) { using (EneterTrace.Entering()) { try { MessageBusMessage aMessage = new MessageBusMessage(EMessageBusRequest.DisconnectClient, clientId, null); object aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage); myMessageBusOutputChannel.SendMessage(aSerializedMessage); } catch (Exception err) { EneterTrace.Warning(TracedObject + ErrorHandler.FailedToCloseConnection, err); } if (notifyFlag) { ProtocolMessage aProtocolMessage = new ProtocolMessage(EProtocolMessageType.CloseConnectionRequest, clientId, null); MessageContext aMessageContext = new MessageContext(aProtocolMessage, ""); NotifyMessageContext(aMessageContext); } } }
public void StartListening(Action <MessageContext> messageHandler) { using (EneterTrace.Entering()) { if (messageHandler == null) { throw new ArgumentNullException("messageHandler is null."); } using (ThreadLock.Lock(myListeningManipulatorLock)) { try { myMessageHandler = messageHandler; myMessageBusOutputChannel.ResponseMessageReceived += OnMessageFromMessageBusReceived; // Open connection with the message bus. myMessageBusOutputChannel.OpenConnection(); // Register service in the message bus. MessageBusMessage aMessage = new MessageBusMessage(EMessageBusRequest.RegisterService, myServiceId, null); object aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage); myMessageBusOutputChannel.SendMessage(aSerializedMessage); } catch { StopListening(); throw; } } } }
public void SendBroadcast(object message) { using (EneterTrace.Entering()) { List <string> aDisconnectedClients = new List <string>(); using (ThreadLock.Lock(myConnectedClients)) { foreach (string aClientId in myConnectedClients.Keys) { try { MessageBusMessage aMessage = new MessageBusMessage(EMessageBusRequest.SendResponseMessage, aClientId, message); object aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage); myMessageBusOutputChannel.SendMessage(aSerializedMessage); } catch (Exception err) { EneterTrace.Error(TracedObject + ErrorHandler.FailedToSendResponseMessage, err); aDisconnectedClients.Add(aClientId); // Note: Exception is not rethrown because if sending to one client fails it should not // affect sending to other clients. } } } // Disconnect failed clients. foreach (String anOutputConnectorAddress in aDisconnectedClients) { CloseConnection(anOutputConnectorAddress, true); } } }
public void SendRequestMessage(object message) { using (EneterTrace.Entering()) { // Note: do not send the client id. It will be automatically assign in the message bus before forwarding the message to the service. // It is done like this due to security reasons. So that some client cannot pretend other client just by sending a different id. MessageBusMessage aMessage = new MessageBusMessage(EMessageBusRequest.SendRequestMessage, "", message); object aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage); myMessageBusOutputChannel.SendMessage(aSerializedMessage); } }
public void SendResponseMessage(string clientId, object message) { using (EneterTrace.Entering()) { try { MessageBusMessage aMessage = new MessageBusMessage(EMessageBusRequest.SendResponseMessage, clientId, message); object aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage); myMessageBusOutputChannel.SendMessage(aSerializedMessage); } catch { CloseConnection(clientId, true); throw; } } }
public void OpenConnection(Action <MessageContext> responseMessageHandler) { using (EneterTrace.Entering()) { if (responseMessageHandler == null) { throw new ArgumentNullException("responseMessageHandler is null."); } using (ThreadLock.Lock(myConnectionManipulatorLock)) { try { // Open physical connection. myResponseMessageHandler = responseMessageHandler; myMessageBusOutputChannel.ResponseMessageReceived += OnMessageFromMessageBusReceived; myMessageBusOutputChannel.ConnectionClosed += OnConnectionWithMessageBusClosed; myMessageBusOutputChannel.OpenConnection(); myOpenConnectionConfirmed.Reset(); // Tell message bus which service shall be associated with this connection. MessageBusMessage aMessage = new MessageBusMessage(EMessageBusRequest.ConnectClient, myServiceId, null); object aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage); myMessageBusOutputChannel.SendMessage(aSerializedMessage); if (!myOpenConnectionConfirmed.WaitOne(myOpenConnectionTimeout)) { throw new TimeoutException(TracedObject + "failed to open the connection within the timeout: " + myOpenConnectionTimeout); } if (!myMessageBusOutputChannel.IsConnected) { throw new InvalidOperationException(TracedObject + ErrorHandler.FailedToOpenConnection); } } catch { CloseConnection(); throw; } } } }
public T Deserialize <T>(object serializedData) { using (EneterTrace.Entering()) { if (serializedData is byte[] == false) { throw new ArgumentException("Input parameter 'serializedData' is not byte[]."); } if (typeof(T) != typeof(MessageBusMessage)) { throw new InvalidOperationException("Data can be deserialized only into" + typeof(MessageBusMessage).Name); } MessageBusMessage aResult; byte[] aData = (byte[])serializedData; using (MemoryStream aStream = new MemoryStream(aData)) { BinaryReader aReader = new BinaryReader(aStream); // Read message bus request. int aRequest = aReader.ReadByte(); EMessageBusRequest aMessageBusRequest = (EMessageBusRequest)aRequest; // Read Id string anId = myEncoderDecoder.ReadPlainString(aReader, Encoding.UTF8, myIsLittleEndian); // Read message data. object aMessageData = null; if (aMessageBusRequest == EMessageBusRequest.SendRequestMessage || aMessageBusRequest == EMessageBusRequest.SendResponseMessage) { aMessageData = myEncoderDecoder.Read(aReader, myIsLittleEndian); } aResult = new MessageBusMessage(aMessageBusRequest, anId, aMessageData); return((T)(object)aResult); } } }
public object Serialize <T>(T dataToSerialize) { using (EneterTrace.Entering()) { if (typeof(T) != typeof(MessageBusMessage)) { throw new InvalidOperationException("Only " + typeof(MessageBusMessage).Name + " can be serialized."); } object aTemp = dataToSerialize; MessageBusMessage aMessage = (MessageBusMessage)aTemp; using (MemoryStream aStream = new MemoryStream()) { BinaryWriter aWriter = new BinaryWriter(aStream); // Write messagebus request. byte aRequestType = (byte)aMessage.Request; aWriter.Write((byte)aRequestType); // Write Id. myEncoderDecoder.WritePlainString(aWriter, aMessage.Id, Encoding.UTF8, myIsLittleEndian); // Write message data. if (aMessage.Request == EMessageBusRequest.SendRequestMessage || aMessage.Request == EMessageBusRequest.SendResponseMessage) { if (aMessage.MessageData == null) { throw new InvalidOperationException("Message data is null."); } myEncoderDecoder.Write(aWriter, aMessage.MessageData, myIsLittleEndian); } return(aStream.ToArray()); } } }
private void OnMessageFromMessageBusReceived(object sender, DuplexChannelMessageEventArgs e) { using (EneterTrace.Entering()) { MessageBusMessage aMessageBusMessage; try { aMessageBusMessage = mySerializer.Deserialize <MessageBusMessage>(e.Message); } catch (Exception err) { EneterTrace.Error(TracedObject + "failed to deserialize message.", err); return; } if (aMessageBusMessage.Request == EMessageBusRequest.ConnectClient) { MessageBusMessage aResponseMessage = new MessageBusMessage(EMessageBusRequest.ConfirmClient, aMessageBusMessage.Id, null); object aSerializedResponse = mySerializer.Serialize <MessageBusMessage>(aResponseMessage); myMessageBusOutputChannel.SendMessage(aSerializedResponse); ProtocolMessage aProtocolMessage = new ProtocolMessage(EProtocolMessageType.OpenConnectionRequest, aMessageBusMessage.Id, null); MessageContext aMessageContext = new MessageContext(aProtocolMessage, e.SenderAddress); IThreadDispatcher aDispatcher = myThreadDispatcherProvider.GetDispatcher(); using (ThreadLock.Lock(myConnectedClients)) { myConnectedClients[aProtocolMessage.ResponseReceiverId] = aDispatcher; } aDispatcher.Invoke(() => NotifyMessageContext(aMessageContext)); } else if (aMessageBusMessage.Request == EMessageBusRequest.DisconnectClient) { ProtocolMessage aProtocolMessage = new ProtocolMessage(EProtocolMessageType.CloseConnectionRequest, aMessageBusMessage.Id, aMessageBusMessage.MessageData); MessageContext aMessageContext = new MessageContext(aProtocolMessage, e.SenderAddress); IThreadDispatcher aDispatcher; using (ThreadLock.Lock(myConnectedClients)) { myConnectedClients.TryGetValue(aProtocolMessage.ResponseReceiverId, out aDispatcher); if (aDispatcher != null) { myConnectedClients.Remove(aProtocolMessage.ResponseReceiverId); } else { aDispatcher = myThreadDispatcherProvider.GetDispatcher(); } } aDispatcher.Invoke(() => NotifyMessageContext(aMessageContext)); } else if (aMessageBusMessage.Request == EMessageBusRequest.SendRequestMessage) { ProtocolMessage aProtocolMessage = new ProtocolMessage(EProtocolMessageType.MessageReceived, aMessageBusMessage.Id, aMessageBusMessage.MessageData); MessageContext aMessageContext = new MessageContext(aProtocolMessage, e.SenderAddress); IThreadDispatcher aDispatcher; using (ThreadLock.Lock(myConnectedClients)) { myConnectedClients.TryGetValue(aProtocolMessage.ResponseReceiverId, out aDispatcher); if (aDispatcher == null) { aDispatcher = myThreadDispatcherProvider.GetDispatcher(); myConnectedClients[aProtocolMessage.ResponseReceiverId] = aDispatcher; } } aDispatcher.Invoke(() => NotifyMessageContext(aMessageContext)); } } }
private void ForwardMessageToService(string clientResponseReceiverId, MessageBusMessage messageFromClient) { using (EneterTrace.Entering()) { TClientContext aClientContext = null; using (ThreadLock.Lock(myConnectionLock)) { aClientContext = myConnectedClients.FirstOrDefault(x => x.ClientResponseReceiverId == clientResponseReceiverId); } if (aClientContext != null) { // Forward the incoming message to the service. IDuplexInputChannel anInputChannel = myServiceConnector.AttachedDuplexInputChannel; if (anInputChannel != null) { aClientContext.ForwardToServiceThreadDispatcher.Invoke( () => { using (EneterTrace.Entering()) { try { // Add the client id into the message. // Note: Because of security reasons we do not expect Ids from the client but using Ids associated with the connection session. // Otherwise it would be possible that some client could use id of another client to pretend a different client. messageFromClient.Id = clientResponseReceiverId; object aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(messageFromClient); anInputChannel.SendResponseMessage(aClientContext.ServiceResponseReceiverId, aSerializedMessage); if (MessageToServiceSent != null) { MessageBusMessageEventArgs anEventArgs = new MessageBusMessageEventArgs(aClientContext.ServiceId, aClientContext.ServiceResponseReceiverId, clientResponseReceiverId, messageFromClient.MessageData); try { MessageToServiceSent(this, anEventArgs); } catch (Exception err) { EneterTrace.Warning(TracedObject + ErrorHandler.DetectedException, err); } } } catch (Exception err) { string anErrorMessage = TracedObject + "failed to send message to the service '" + aClientContext.ServiceId + "'."; EneterTrace.Error(anErrorMessage, err); UnregisterService(aClientContext.ServiceResponseReceiverId); } } }); } } else { string anErrorMessage = TracedObject + "failed to send message to the service because the client was not found."; EneterTrace.Warning(anErrorMessage); } } }
private void UnregisterClient(string clientResponseReceiverId, bool sendCloseConnectionToServiceFlag, bool disconnectClientFlag) { using (EneterTrace.Entering()) { // Unregistering client. TClientContext aClientContext = null; using (ThreadLock.Lock(myConnectionLock)) { myConnectedClients.RemoveWhere(x => { if (x.ClientResponseReceiverId == clientResponseReceiverId) { aClientContext = x; return(true); } return(false); }); } if (aClientContext != null) { if (sendCloseConnectionToServiceFlag) { try { // Send close connection message to the service. MessageBusMessage aMessage = new MessageBusMessage(EMessageBusRequest.DisconnectClient, aClientContext.ClientResponseReceiverId, null); object aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage); IDuplexInputChannel anInputChannel = myServiceConnector.AttachedDuplexInputChannel; if (anInputChannel != null) { anInputChannel.SendResponseMessage(aClientContext.ServiceResponseReceiverId, aSerializedMessage); } } catch (Exception err) { string anErrorMessage = TracedObject + ErrorHandler.FailedToCloseConnection; EneterTrace.Warning(anErrorMessage, err); } } // Disconnecting the client. if (disconnectClientFlag) { IDuplexInputChannel anInputChannel1 = myClientConnector.AttachedDuplexInputChannel; if (anInputChannel1 != null) { anInputChannel1.DisconnectResponseReceiver(aClientContext.ClientResponseReceiverId); } } if (ClientDisconnected != null) { MessageBusClientEventArgs anEventArgs = new MessageBusClientEventArgs(aClientContext.ServiceId, aClientContext.ServiceResponseReceiverId, clientResponseReceiverId); try { ClientDisconnected(this, anEventArgs); } catch (Exception err) { EneterTrace.Warning(TracedObject + ErrorHandler.DetectedException, err); } } } } }
private void RegisterClient(string clientResponseReceiverId, string serviceId) { using (EneterTrace.Entering()) { bool anIsNewClientConnected = false; TClientContext aClientContext = null; using (ThreadLock.Lock(myConnectionLock)) { aClientContext = myConnectedClients.FirstOrDefault(x => x.ClientResponseReceiverId == clientResponseReceiverId); // If such client does not exist yet then create it. if (aClientContext == null) { TServiceContext aServiceContext = myConnectedServices.FirstOrDefault(x => x.ServiceId == serviceId); // If requested service exists. if (aServiceContext != null) { aClientContext = new TClientContext(clientResponseReceiverId, serviceId, aServiceContext.ServiceResponseReceiverId); myConnectedClients.Add(aClientContext); anIsNewClientConnected = true; } } } if (anIsNewClientConnected) { // Send open connection message to the service. try { MessageBusMessage aMessage = new MessageBusMessage(EMessageBusRequest.ConnectClient, clientResponseReceiverId, null); object aSerializedMessage = mySerializer.Serialize <MessageBusMessage>(aMessage); IDuplexInputChannel anInputChannel = myServiceConnector.AttachedDuplexInputChannel; if (anInputChannel != null) { anInputChannel.SendResponseMessage(aClientContext.ServiceResponseReceiverId, aSerializedMessage); } } catch (Exception err) { EneterTrace.Warning(TracedObject + "failed to send open connection message to the service '" + aClientContext.ServiceId + "'.", err); // Note: The service should not be disconnected from the message bus when not available. // Because it can be "just" overloaded. So only this new client will be disconnected from the message bus. UnregisterClient(clientResponseReceiverId, false, true); } } else { if (aClientContext != null) { EneterTrace.Warning(TracedObject + "failed to connect the client already exists. The connection will be closed."); UnregisterClient(clientResponseReceiverId, false, true); } else { EneterTrace.Warning(TracedObject + "failed to connec the client because the service '" + serviceId + "' does not exist. The connection will be closed."); UnregisterClient(clientResponseReceiverId, false, true); } } } }