public void StopListening() { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myConnectedClients)) { foreach (KeyValuePair<string, NamedPipeSender> aClient in myConnectedClients) { try { CloseConnection(aClient.Key, aClient.Value); } catch (Exception err) { EneterTrace.Warning(TracedObject + ErrorHandler.FailedToCloseConnection, err); } } myConnectedClients.Clear(); } using (ThreadLock.Lock(myListeningManipulatorLock)) { if (myReceiver != null) { myReceiver.StopListening(); myReceiver = null; } myMessageHandler = null; } } }
public void SendMessage(string receiverId, object message) { using (EneterTrace.Entering()) { // Get the message handler Action <object> aMessageHandler = null; using (ThreadLock.Lock(myRegisteredMessageHandlers)) { myRegisteredMessageHandlers.TryGetValue(receiverId, out aMessageHandler); } // If the message handler was found then send the message if (aMessageHandler != null) { aMessageHandler(message); } else { string anError = "The receiver '" + receiverId + "' does not exist."; EneterTrace.Error(anError); throw new InvalidOperationException(anError); } } }
public virtual void AttachDuplexInputChannel(IDuplexInputChannel duplexInputChannel) { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myDuplexInputChannelManipulatorLock)) { Attach(duplexInputChannel); try { AttachedDuplexInputChannel.StartListening(); } catch (Exception err) { try { DetachDuplexInputChannel(); } catch { // Ignore exception in exception. } EneterTrace.Error(TracedObject + ErrorHandler.FailedToStartListening, err); throw; } } } }
public void AttachDuplexInputChannel(IDuplexInputChannel duplexInputChannel) { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myDuplexInputChannels)) { Attach(duplexInputChannel); try { duplexInputChannel.StartListening(); } catch (Exception err) { // Try to clean after the failure try { DetachDuplexInputChannel(duplexInputChannel.ChannelId); } catch { } string aMessage = TracedObject + "failed to start listening for '" + duplexInputChannel.ChannelId + "'."; EneterTrace.Error(aMessage, err); throw; } } } }
public void StopListening() { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myListeningManipulatorLock)) { // Indicate, that the timer responsible for checking if response receivers are timeouted (i.e. exceeded the max offline time) // shall stop. myMaxOfflineCheckerRequestedToStop = true; try { myInputChannel.StopListening(); } catch (Exception err) { EneterTrace.Warning(TracedObject + ErrorHandler.IncorrectlyStoppedListening, err); } using (ThreadLock.Lock(myResponseReceivers)) { myBroadcasts.Clear(); myResponseReceivers.Clear(); } myInputChannel.ResponseReceiverConnected -= OnResponseReceiverConnected; myInputChannel.ResponseReceiverDisconnected -= OnResponseReceiverDisconnected; myInputChannel.MessageReceived -= OnMessageReceived; } } }
public void SendMessage(object message) { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myConnectionManipulatorLock)) { if (!IsConnected) { string aMessage = TracedObject + ErrorHandler.FailedToSendMessageBecauseNotConnected; EneterTrace.Error(aMessage); throw new InvalidOperationException(aMessage); } try { // Send the message. myOutputConnector.SendRequestMessage(message); } catch (Exception err) { EneterTrace.Error(TracedObject + ErrorHandler.FailedToSendMessage, err); CleanAfterConnection(true, true); throw; } } } }
/// <summary> /// The method is called when a message from the attached duplex input channel is received. /// The received message is wrapped and sent to the duplex output channel. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnMessageReceived(object sender, DuplexChannelMessageEventArgs e) { using (EneterTrace.Entering()) { if (!IsDuplexOutputChannelAttached) { EneterTrace.Error(TracedObject + "is not attached to the duplex output channel."); return; } try { using (ThreadLock.Lock(myDuplexInputChannels)) { myDuplexInputChannels[e.ChannelId].ResponseReceiverId = e.ResponseReceiverId; } ISerializer aSerializer = mySerializer.ForResponseReceiver(e.ResponseReceiverId); object aMessage = DataWrapper.Wrap(e.ChannelId, e.Message, aSerializer); AttachedDuplexOutputChannel.SendMessage(aMessage); } catch (Exception err) { EneterTrace.Error(TracedObject + "failed to send the message to the duplex output channel '" + e.ChannelId + "'.", err); } } }
public virtual void DetachDuplexInputChannel() { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myDuplexInputChannelContextManipulatorLock)) { foreach (TDuplexInputChannelContext aDuplexInputChannelContext in myDuplexInputChannelContexts) { // Go via all connections with clients and close them. CloseConnections(aDuplexInputChannelContext.OpenConnections); try { aDuplexInputChannelContext.AttachedDuplexInputChannel.StopListening(); } catch (Exception err) { EneterTrace.Warning(TracedObject + "failed to correctly detach the duplex input channel '" + aDuplexInputChannelContext.AttachedDuplexInputChannel + "'.", err); } aDuplexInputChannelContext.AttachedDuplexInputChannel.ResponseReceiverDisconnected -= OnDuplexInputChannelResponseReceiverDisconnected; aDuplexInputChannelContext.AttachedDuplexInputChannel.MessageReceived -= OnMessageReceived; } myDuplexInputChannelContexts.Clear(); } } }
public virtual void DetachDuplexInputChannel(string channelId) { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myDuplexInputChannelContextManipulatorLock)) { // Get the context of the requested input channel. TDuplexInputChannelContext aDuplexInputChannelContext = myDuplexInputChannelContexts.FirstOrDefault(x => x.AttachedDuplexInputChannel.ChannelId == channelId); if (aDuplexInputChannelContext != null) { try { // Go via all connections with clients and close them. CloseConnections(aDuplexInputChannelContext.OpenConnections); // Stop listening to the duplex input channel. aDuplexInputChannelContext.AttachedDuplexInputChannel.StopListening(); } finally { aDuplexInputChannelContext.AttachedDuplexInputChannel.ResponseReceiverDisconnected -= OnDuplexInputChannelResponseReceiverDisconnected; aDuplexInputChannelContext.AttachedDuplexInputChannel.MessageReceived -= OnMessageReceived; myDuplexInputChannelContexts.RemoveWhere(x => x.AttachedDuplexInputChannel.ChannelId == aDuplexInputChannelContext.AttachedDuplexInputChannel.ChannelId); } } } } }
/// <summary> /// Returns true if somebody is listening to the given uri. /// </summary> /// <param name="uri"></param> /// <returns></returns> public static bool IsListening(Uri uri) { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myListeners)) { // Get all possible listening endpoints. // Note: if URI contains hostname (instead of IP) then it returns false if none endpoints is listening. IEnumerable <IPEndPoint> anEndPoints = GetEndPoints(uri); foreach (IPEndPoint anEndPoint in anEndPoints) { // Figure out if exist a host listener for the endpoint. HostListenerBase aHostListener = GetHostListener(anEndPoint); if (aHostListener != null) { // Figure out if the path listener exists. if (aHostListener.ExistListener(uri)) { return(true); } } } return(false); } } }
public static void StopListening(Uri uri) { using (EneterTrace.Entering()) { try { using (ThreadLock.Lock(myListeners)) { // Get all possible listening endpoints. IEnumerable <IPEndPoint> anEndPoints = GetEndPoints(uri); foreach (IPEndPoint anEndPoint in anEndPoints) { // Figure out if exist a host listener for the endpoint. HostListenerBase aHostListener = GetHostListener(anEndPoint); if (aHostListener != null) { // Unregister the path from the host listener. aHostListener.UnregisterListener(uri); // If there is no a path listener then nobody is interested in incoming messages // and the TCP listening can be stopped. if (aHostListener.ExistAnyListener() == false) { myListeners.Remove(aHostListener); } } } } } catch (Exception err) { EneterTrace.Warning(TracedObject + "failed to stop listening.", err); } } }
public void SendBroadcast(object message) { using (EneterTrace.Entering()) { List <string> aDisconnectedClients = new List <string>(); using (ThreadLock.Lock(myConnectedClients)) { // Send the response message to all connected clients. foreach (KeyValuePair <string, TClientContext> aClientContext in myConnectedClients) { try { // Send the response message. object anEncodedMessage = myProtocolFormatter.EncodeMessage(aClientContext.Key, message); aClientContext.Value.SendResponseMessage(anEncodedMessage); } catch (Exception err) { EneterTrace.Error(TracedObject + ErrorHandler.FailedToSendResponseMessage, err); aDisconnectedClients.Add(aClientContext.Key); // 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 SendResponseMessage(string outputConnectorAddress, object message) { using (EneterTrace.Entering()) { TClientContext aClientContext; using (ThreadLock.Lock(myConnectedClients)) { myConnectedClients.TryGetValue(outputConnectorAddress, out aClientContext); } if (aClientContext == null) { throw new InvalidOperationException("The connection with client '" + outputConnectorAddress + "' is not open."); } try { object anEncodedMessage = myProtocolFormatter.EncodeMessage(outputConnectorAddress, message); aClientContext.SendResponseMessage(anEncodedMessage); } catch { CloseConnection(outputConnectorAddress, true); throw; } } }
public void StopListening() { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myConnectedClients)) { foreach (KeyValuePair <string, TClientContext> aClientContext in myConnectedClients) { try { aClientContext.Value.CloseConnection(); } catch (Exception err) { EneterTrace.Warning(TracedObject + ErrorHandler.FailedToCloseConnection, err); } } myConnectedClients.Clear(); } using (ThreadLock.Lock(myListeningManipulatorLock)) { myTcpListenerProvider.StopListening(); myMessageHandler = null; } } }
public void UnregisterListener(Uri address) { using (EneterTrace.Entering()) { try { using (ThreadLock.Lock(myHandlers)) { // Remove handler for that path. myHandlers.RemoveWhere(x => x.Key.AbsolutePath == address.AbsolutePath); // If there is no the end point then nobody is handling messages and the listening can be stopped. if (myHandlers.Count == 0) { myTcpListener.StopListening(); } } } catch (Exception err) { String anErrorMessage = TracedObject + "failed to unregister path-listener."; EneterTrace.Warning(anErrorMessage, err); } } }
protected override void OnConnectionOpened(object sender, DuplexChannelEventArgs e) { using (EneterTrace.Entering()) { // Note: Following subscribing cannot block the thread processing events from duplex output channel // because a deadlock can occur. Because if the lock would stop this thread other messages could not be processed. EneterThreadPool.QueueUserWorkItem(() => { // Recover remote subscriptions at service. foreach (KeyValuePair <string, RemoteEvent> aRemoteEvent in myRemoteEvents) { // Note: In Java, the following 'lock' section is located in RemoteEvent class. // It is not possible to locate it there in C# because inner class cannot reach methods of outer class. using (ThreadLock.Lock(aRemoteEvent.Value.SubscribeUnsubscribeLock)) { if (aRemoteEvent.Value.Subscribers.Count > 0) { SubscribeAtService(aRemoteEvent.Key); } } } // Forward the event. myThreadDispatcher.Invoke(() => Notify(ConnectionOpened, e)); }); } }
/// <summary> /// Starts the thread where the instance loops trying to serve client requests. /// </summary> public void StartListening(Action <Stream> messageHandler) { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myListeningManipulatorLock)) { if (IsListening) { EneterTrace.Error(ErrorHandler.IsAlreadyListening); throw new InvalidOperationException(ErrorHandler.IsAlreadyListening); } if (messageHandler == null) { throw new ArgumentNullException("The input parameter messageHandler is null."); } myStopListeningRequestFlag = false; myMessageHandler = messageHandler; // Note: It must be PipeOptions.Asynchronous because otherwise it is not possible // to close the pipe and interrupt so the waiting. myPipeServer = new NamedPipeServerStream(myPipeName, PipeDirection.In, myMaxNumPipeInstancies, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 32768, 0, myPipeSecurity); myListeningThread = new Thread(DoListening); myListeningThread.Start(); } } }
public void StartListening(Action <MessageContext> messageHandler) { using (EneterTrace.Entering()) { if (messageHandler == null) { throw new ArgumentNullException("messageHandler is null."); } using (ThreadLock.Lock(myListenerManipulatorLock)) { try { myMessageHandler = messageHandler; myMessagingProvider.RegisterMessageHandler(myInputConnectorAddress, OnRequestMessageReceived); myIsListeningFlag = true; } catch { StopListening(); throw; } } } }
private void CleanAfterConnection(bool sendCloseMessageFlag, bool notifyConnectionClosedFlag) { using (EneterTrace.Entering()) { bool aConnectionWasCorrectlyOpen = false; using (ThreadLock.Lock(myConnectionManipulatorLock)) { if (sendCloseMessageFlag) { try { myOutputConnector.CloseConnection(); } catch (Exception err) { EneterTrace.Warning(TracedObject + ErrorHandler.FailedToCloseConnection, err); } } // Note: the notification must run outside the lock because of potententional deadlock. aConnectionWasCorrectlyOpen = myConnectionIsCorrectlyOpen; myConnectionIsCorrectlyOpen = false; } // Notify the connection closed only if it was successfuly open before. // E.g. It will be not notified if the CloseConnection() is called for already closed connection. if (aConnectionWasCorrectlyOpen && notifyConnectionClosedFlag) { Dispatcher.Invoke(() => Notify(ConnectionClosed)); } } }
public void SendBroadcast(object message) { using (EneterTrace.Entering()) { List <string> aDisconnectedClients = new List <string>(); using (ThreadLock.Lock(myConnectedClients)) { // Send the response message to all connected clients. foreach (string aResponseReceiverId in myConnectedClients) { try { // Send the response message. SendResponseMessage(aResponseReceiverId, message); } catch (Exception err) { EneterTrace.Error(TracedObject + ErrorHandler.FailedToSendResponseMessage, err); aDisconnectedClients.Add(aResponseReceiverId); // 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); } } }
private void Attach(IDuplexInputChannel duplexInputChannel) { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myDuplexInputChannels)) { if (duplexInputChannel == null) { string aMessage = TracedObject + "failed to attach duplex input channel because the input parameter 'duplexInputChannel' is null."; EneterTrace.Error(aMessage); throw new ArgumentNullException(aMessage); } if (string.IsNullOrEmpty(duplexInputChannel.ChannelId)) { string aMessage = TracedObject + "failed to attach duplex input channel because the input parameter 'duplexInputChannel' has empty or null channel id."; EneterTrace.Error(aMessage); throw new ArgumentException(aMessage); } if (myDuplexInputChannels.ContainsKey(duplexInputChannel.ChannelId)) { string anErrorMessage = TracedObject + "failed to attach duplex input channel because the channel with id '" + duplexInputChannel.ChannelId + "' is already attached."; EneterTrace.Error(anErrorMessage); throw new InvalidOperationException(anErrorMessage); } myDuplexInputChannels[duplexInputChannel.ChannelId] = new TDuplexInputChannel(duplexInputChannel); duplexInputChannel.MessageReceived += OnMessageReceived; } } }
private void CleanConnection(bool sendMessageFlag) { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myConnectionManipulatorLock)) { if (myReceiver != null) { myReceiver.StopListening(); myReceiver = null; } if (mySender != null) { if (sendMessageFlag) { try { mySender.SendMessage(x => myProtocolFormatter.EncodeCloseConnectionMessage(myOutputConnectorAddress, x)); } catch (Exception err) { EneterTrace.Warning(TracedObject + "failed to send close connection message.", err); } } mySender.Dispose(); mySender = null; } } } }
public void StartListening() { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myListeningManipulatorLock)) { myInputChannel.ResponseReceiverConnected += OnResponseReceiverConnected; myInputChannel.ResponseReceiverDisconnected += OnResponseReceiverDisconnected; myInputChannel.MessageReceived += OnMessageReceived; try { myInputChannel.StartListening(); } catch (Exception err) { EneterTrace.Error(TracedObject + ErrorHandler.FailedToStartListening, err); StopListening(); throw; } myMaxOfflineCheckerRequestedToStop = false; } } }
public void OpenConnection(Action <MessageContext> responseMessageHandler) { using (EneterTrace.Entering()) { // If it shall listen to responses then check the responseMessageHandler. if (responseMessageHandler == null) { throw new InvalidOperationException("responseMessageHandler is null."); } using (ThreadLock.Lock(myConnectionManipulatorLock)) { try { // Send open connection message to open the connection. // When DuplexInputChannel receives the open connection message it creates // shared memory for sending response messages. mySender = new SharedMemorySender(myInputConnectorAddress, true, myConnectTimeout, mySendTimeout, myMaxMessageSize, mySecurity); mySender.SendMessage(x => myProtocolFormatter.EncodeOpenConnectionMessage(myOutputConnectorAddress, x)); // The input connector has opened the shared memory for responses // so we can start listening from it. // (It will open existing memory mapped file.) myResponseMessageHandler = responseMessageHandler; myReceiver = new SharedMemoryReceiver(myOutputConnectorAddress, true, myConnectTimeout, myMaxMessageSize, mySecurity); myReceiver.StartListening(HandleResponseMessage); } catch { CloseConnection(); throw; } } } }
private void OnMaxOfflineTimeCheckTick(object o) { using (EneterTrace.Entering()) { // Do nothing if there is a request to stop. if (myMaxOfflineCheckerRequestedToStop) { return; } List <TBufferedResponseReceiver> aTimeoutedResponseReceivers = new List <TBufferedResponseReceiver>(); DateTime aCurrentCheckTime = DateTime.Now; bool aTimerShallContinueFlag; using (ThreadLock.Lock(myResponseReceivers)) { // Remove all expired broadcasts. myBroadcasts.RemoveAll(x => aCurrentCheckTime - x.SentAt > myMaxOfflineTime); // Remove all not connected response receivers which exceeded the max offline timeout. myResponseReceivers.RemoveWhere(x => { // If disconnected and max offline time is exceeded. if (!x.IsOnline && aCurrentCheckTime - x.OfflineStartedAt > myMaxOfflineTime) { aTimeoutedResponseReceivers.Add(x); // Indicate, the response receiver can be removed. return(true); } // Response receiver will not be removed. return(false); }); aTimerShallContinueFlag = myResponseReceivers.Count > 0; } // Notify disconnected response receivers. foreach (TBufferedResponseReceiver aResponseReceiver in aTimeoutedResponseReceivers) { // Stop disconnecting if the we are requested to stop. if (myMaxOfflineCheckerRequestedToStop) { return; } // Invoke the event in the correct thread. Dispatcher.Invoke(() => Notify(ResponseReceiverDisconnected, new ResponseReceiverEventArgs(aResponseReceiver.ResponseReceiverId, aResponseReceiver.ClientAddress), false)); } // If the timer checking the timeout for response receivers shall continue if (!myMaxOfflineCheckerRequestedToStop && aTimerShallContinueFlag) { myMaxOfflineChecker.Change(300, -1); } } }
public void StartListening(Action <_TClientContext> connectionHandler) { using (EneterTrace.Entering()) { try { using (ThreadLock.Lock(myListeningManipulatorLock)) { if (IsListening) { string aMessage = TracedObject + ErrorHandler.IsAlreadyListening; EneterTrace.Error(aMessage); throw new InvalidOperationException(aMessage); } if (connectionHandler == null) { throw new ArgumentNullException("The input parameter connectionHandler is null."); } myConnectionHandler = connectionHandler; HostListenerController.StartListening(Address, myHostListenerFactory, myConnectionHandler, mySecurityFactory); } } catch (Exception err) { EneterTrace.Error(TracedObject + ErrorHandler.FailedToStartListening, err); throw; } } }
private void Attach(IDuplexInputChannel duplexInputChannel) { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myDuplexInputChannelManipulatorLock)) { if (duplexInputChannel == null) { string aMessage = TracedObject + "failed to attach duplex input channel because the input parameter 'duplexInputChannel' is null."; EneterTrace.Error(aMessage); throw new ArgumentNullException(aMessage); } if (string.IsNullOrEmpty(duplexInputChannel.ChannelId)) { string aMessage = TracedObject + "failed to attach duplex input channel because the input parameter 'duplexInputChannel' has empty or null channel id."; EneterTrace.Error(aMessage); throw new ArgumentException(aMessage); } if (IsDuplexInputChannelAttached) { string aMessage = TracedObject + "failed to attach duplex input channel '" + duplexInputChannel.ChannelId + "' because the channel is already attached."; EneterTrace.Error(aMessage); throw new InvalidOperationException(aMessage); } AttachedDuplexInputChannel = duplexInputChannel; AttachedDuplexInputChannel.MessageReceived += OnRequestMessageReceived; AttachedDuplexInputChannel.ResponseReceiverConnected += OnResponseReceiverConnected; AttachedDuplexInputChannel.ResponseReceiverDisconnected += OnResponseReceiverDisconnected; } } }
public void StartListening() { using (EneterTrace.Entering()) { using (ThreadLock.Lock(myListeningManipulatorLock)) { // If the channel is already listening. if (IsListening) { string aMessage = TracedObject + ErrorHandler.IsAlreadyListening; EneterTrace.Error(aMessage); throw new InvalidOperationException(aMessage); } try { // Start listen to messages. myInputConnector.StartListening(HandleMessage); } catch (Exception err) { EneterTrace.Error(TracedObject + ErrorHandler.FailedToStartListening, err); // The listening did not start correctly. // So try to clean. StopListening(); throw; } } } }
public static TServiceInterface CreateInstance <TServiceInterface>(Func <string, object[], object> call, Action <string, Delegate, Action <object, EventArgs> > subscribe, Action <string, Delegate> unsubscribe) { using (EneterTrace.Entering()) { Type anInterfaceType = typeof(TServiceInterface); if (!anInterfaceType.IsInterface) { string anErrorMessage = "Provided service interface '" + anInterfaceType.Name + "' is not interface."; EneterTrace.Error(anErrorMessage); throw new ArgumentException(anErrorMessage); } Type anImplementedClass = null; using (ThreadLock.Lock(myImplementedInterfaces)) { myImplementedInterfaces.TryGetValue(anInterfaceType, out anImplementedClass); if (anImplementedClass == null) { // Dynamically implement proxy for the given interface. SoftwareEngineer anEngineer = new SoftwareEngineer(); anImplementedClass = anEngineer.ImplementProxy(anInterfaceType); myImplementedInterfaces[anInterfaceType] = anImplementedClass; } // Instantiate the proxy. TServiceInterface aProxyInstance = (TServiceInterface)Activator.CreateInstance(anImplementedClass, call, subscribe, unsubscribe); return(aProxyInstance); } } }
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; myReceiver = new NamedPipeReceiver(myInputConnectorAddress, myNumberOfListeningInstances, myConnectionTimeout, mySecurity); myReceiver.StartListening(OnRequestMessageReceived); } catch { StopListening(); throw; } } } }