private void CloseConnection(string outputConnectorAddress, TClientContext clientContext)
        {
            using (EneterTrace.Entering())
            {
                try
                {
                    object anEncodedMessage = myProtocolFormatter.EncodeCloseConnectionMessage(outputConnectorAddress);
                    if (anEncodedMessage != null)
                    {
                        clientContext.SendResponseMessage(anEncodedMessage);
                    }
                }
                catch (Exception err)
                {
                    EneterTrace.Warning(TracedObject + ErrorHandler.FailedToCloseConnection, err);
                }

                clientContext.CloseConnection();
            }
        }
Esempio n. 2
0
        private void ForwardMessageToService(string clientResponseReceiverId, MessageBusMessage messageFromClient)
        {
            using (EneterTrace.Entering())
            {
                TClientContext aClientContext = null;
                using (ThreadLock.Lock(myConnectionLock))
                {
                    aClientContext = myConnectedClients.FirstOrDefault(x => x.ClientResponseReceiverId == clientResponseReceiverId);
                }

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

                                    anInputChannel.SendResponseMessage(aClientContext.ServiceResponseReceiverId, aSerializedMessage);

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

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

                        return(false);
                    });
                }

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

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

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

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

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

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

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

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

                        // Note: The service should not be disconnected from the message bus when not available.
                        //       Because it can be "just" overloaded. So only this new client will be disconnected from the message bus.
                        UnregisterClient(clientResponseReceiverId, false, true);
                    }
                }
                else
                {
                    if (aClientContext != null)
                    {
                        EneterTrace.Warning(TracedObject + "failed to connect the client already exists. The connection will be closed.");
                        UnregisterClient(clientResponseReceiverId, false, true);
                    }
                    else
                    {
                        EneterTrace.Warning(TracedObject + "failed to connec the client because the service '" + serviceId + "' does not exist. The connection will be closed.");
                        UnregisterClient(clientResponseReceiverId, false, true);
                    }
                }
            }
        }
Esempio n. 5
0
        private void HandleConnection(TcpClient tcpClient)
        {
            using (EneterTrace.Entering())
            {
                IPEndPoint anEndPoint = tcpClient.Client.RemoteEndPoint as IPEndPoint;
                string     aClientIp  = (anEndPoint != null) ? anEndPoint.ToString() : "";

                Stream anInputOutputStream = null;

                TClientContext aClientContext = null;
                string         aClientId      = null;

                try
                {
                    tcpClient.SendTimeout       = mySendTimeout;
                    tcpClient.ReceiveTimeout    = myReceiveTimeout;
                    tcpClient.SendBufferSize    = mySendBuffer;
                    tcpClient.ReceiveBufferSize = myReceiveBuffer;

                    // If the security communication is required, then wrap the network stream into the security stream.
                    anInputOutputStream = mySecurityStreamFactory.CreateSecurityStreamAndAuthenticate(tcpClient.GetStream());
                    aClientContext      = new TClientContext(anInputOutputStream, aClientIp);

                    // If current protocol formatter does not support OpenConnection message
                    // then open the connection now.
                    if (!myProtocolUsesOpenConnectionMessage)
                    {
                        // Generate client id.
                        aClientId = Guid.NewGuid().ToString();
                        using (ThreadLock.Lock(myConnectedClients))
                        {
                            myConnectedClients[aClientId] = aClientContext;
                        }

                        ProtocolMessage anOpenConnectionProtocolMessage = new ProtocolMessage(EProtocolMessageType.OpenConnectionRequest, aClientId, null);
                        MessageContext  aMessageContext = new MessageContext(anOpenConnectionProtocolMessage, aClientIp);
                        NotifyMessageContext(aMessageContext);
                    }

                    // While the stop of listening is not requested and the connection is not closed.
                    while (true)
                    {
                        ProtocolMessage aProtocolMessage = myProtocolFormatter.DecodeMessage((Stream)anInputOutputStream);

                        // If the stream was not closed.
                        if (aProtocolMessage != null)
                        {
                            // Note: Due to security reasons ignore close connection message in TCP.
                            //       So that it is not possible that somebody will just send a close message which will have id of somebody else.
                            //       The TCP connection will be closed when the client closes the socket.
                            if (aProtocolMessage.MessageType != EProtocolMessageType.CloseConnectionRequest)
                            {
                                MessageContext aMessageContext = new MessageContext(aProtocolMessage, aClientIp);

                                // If open connection message is received and the current protocol formatter uses open connection message
                                // then create the connection now.
                                if (aProtocolMessage.MessageType == EProtocolMessageType.OpenConnectionRequest &&
                                    myProtocolUsesOpenConnectionMessage)
                                {
                                    // Note: if client id is already set then it means this client has already open connection.
                                    if (string.IsNullOrEmpty(aClientId))
                                    {
                                        aClientId = !string.IsNullOrEmpty(aProtocolMessage.ResponseReceiverId) ? aProtocolMessage.ResponseReceiverId : Guid.NewGuid().ToString();

                                        using (ThreadLock.Lock(myConnectedClients))
                                        {
                                            if (!myConnectedClients.ContainsKey(aClientId))
                                            {
                                                myConnectedClients[aClientId] = aClientContext;
                                            }
                                            else
                                            {
                                                // Note: if the client id already exists then the connection cannot be open
                                                //       and the connection with this  client will be closed.
                                                EneterTrace.Warning(TracedObject + "could not open connection for client '" + aClientId + "' because the client with same id is already connected.");
                                                break;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        EneterTrace.Warning(TracedObject + "the client '" + aClientId + "' has already open connection.");
                                    }
                                }

                                // Ensure that nobody will try to use id of somebody else.
                                aMessageContext.ProtocolMessage.ResponseReceiverId = aClientId;
                                NotifyMessageContext(aMessageContext);
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                finally
                {
                    // Remove client from connected clients.
                    if (aClientId != null)
                    {
                        using (ThreadLock.Lock(myConnectedClients))
                        {
                            myConnectedClients.Remove(aClientId);
                        }
                    }

                    // If the disconnection comes from the client (and not from the service).
                    if (aClientContext != null && !aClientContext.IsClosedByService)
                    {
                        ProtocolMessage aCloseProtocolMessage = new ProtocolMessage(EProtocolMessageType.CloseConnectionRequest, aClientId, null);
                        MessageContext  aMessageContext       = new MessageContext(aCloseProtocolMessage, aClientIp);

                        // Notify duplex input channel about the disconnection.
                        NotifyMessageContext(aMessageContext);
                    }

                    if (anInputOutputStream != null)
                    {
                        anInputOutputStream.Close();
                    }
                }
            }
        }
        private void OnRequestMessageReceived(byte[] datagram, EndPoint clientAddress)
        {
            using (EneterTrace.Entering())
            {
                if (datagram == null && clientAddress == null)
                {
                    // The listening got interrupted so nothing to do.
                    return;
                }

                // Get the sender IP address.
                string aClientIp = (clientAddress != null) ? ((IPEndPoint)clientAddress).ToString() : "";

                ProtocolMessage aProtocolMessage = myProtocolFormatter.DecodeMessage(datagram);

                if (aProtocolMessage != null)
                {
                    if (aProtocolMessage.MessageType == EProtocolMessageType.OpenConnectionRequest)
                    {
                        if (!string.IsNullOrEmpty(aProtocolMessage.ResponseReceiverId))
                        {
                            using (ThreadLock.Lock(myConnectedClients))
                            {
                                if (myMaxAmountOfConnections > -1 && myConnectedClients.Count >= myMaxAmountOfConnections)
                                {
                                    TClientContext aClientContext = new TClientContext(myReceiver, (IPEndPoint)clientAddress);
                                    CloseConnection(aProtocolMessage.ResponseReceiverId, aClientContext);

                                    EneterTrace.Warning(TracedObject + "could not open connection for client '" + aProtocolMessage.ResponseReceiverId + "' because the maximum number of connections = '" + myMaxAmountOfConnections + "' was exceeded.");
                                    return;
                                }

                                if (!myConnectedClients.ContainsKey(aProtocolMessage.ResponseReceiverId))
                                {
                                    TClientContext aClientContext = new TClientContext(myReceiver, (IPEndPoint)clientAddress);
                                    myConnectedClients[aProtocolMessage.ResponseReceiverId] = aClientContext;
                                }
                                else
                                {
                                    EneterTrace.Warning(TracedObject + "could not open connection for client '" + aProtocolMessage.ResponseReceiverId + "' because the client with same id is already connected.");
                                }
                            }
                        }
                        else
                        {
                            EneterTrace.Warning(TracedObject + "could not connect a client because response recevier id was not available in open connection message.");
                        }
                    }
                    else if (aProtocolMessage.MessageType == EProtocolMessageType.CloseConnectionRequest)
                    {
                        if (!string.IsNullOrEmpty(aProtocolMessage.ResponseReceiverId))
                        {
                            using (ThreadLock.Lock(myConnectedClients))
                            {
                                myConnectedClients.Remove(aProtocolMessage.ResponseReceiverId);
                            }
                        }
                    }

                    MessageContext aMessageContext = new MessageContext(aProtocolMessage, aClientIp);
                    NotifyMessageContext(aMessageContext);
                }
            }
        }
        private void HandleConnection(IWebSocketClientContext client)
        {
            using (EneterTrace.Entering())
            {
                string aClientIp = (client.ClientEndPoint != null) ? client.ClientEndPoint.ToString() : "";

                TClientContext aClientContext = new TClientContext(client);
                string         aClientId      = null;
                try
                {
                    client.SendTimeout    = mySendTimeout;
                    client.ReceiveTimeout = myReceiveTimeout;

                    // If protocol formatter does not use OpenConnection message.
                    if (!myProtocolUsesOpenConnectionMessage)
                    {
                        aClientId = Guid.NewGuid().ToString();
                        using (ThreadLock.Lock(myConnectedClients))
                        {
                            myConnectedClients[aClientId] = aClientContext;
                        }

                        ProtocolMessage anOpenConnectionProtocolMessage = new ProtocolMessage(EProtocolMessageType.OpenConnectionRequest, aClientId, null);
                        MessageContext  aMessageContext = new MessageContext(anOpenConnectionProtocolMessage, aClientIp);
                        NotifyMessageContext(aMessageContext);
                    }

                    while (true)
                    {
                        // Block until a message is received or the connection is closed.
                        WebSocketMessage aWebSocketMessage = client.ReceiveMessage();

                        if (aWebSocketMessage != null && myMessageHandler != null)
                        {
                            ProtocolMessage aProtocolMessage = myProtocolFormatter.DecodeMessage((Stream)aWebSocketMessage.InputStream);

                            // Note: security reasons ignore close connection message in WebSockets.
                            //       So that it is not possible that somebody will just send a close message which will have id of somebody else.
                            //       The connection will be closed when the client closes the socket.
                            if (aProtocolMessage != null && aProtocolMessage.MessageType != EProtocolMessageType.CloseConnectionRequest)
                            {
                                MessageContext aMessageContext = new MessageContext(aProtocolMessage, aClientIp);

                                // If protocol formatter uses open connection message to create the connection.
                                if (aProtocolMessage.MessageType == EProtocolMessageType.OpenConnectionRequest &&
                                    myProtocolUsesOpenConnectionMessage)
                                {
                                    // Note: if client id is already set then it means this client has already open connection.
                                    if (string.IsNullOrEmpty(aClientId))
                                    {
                                        aClientId = !string.IsNullOrEmpty(aProtocolMessage.ResponseReceiverId) ? aProtocolMessage.ResponseReceiverId : Guid.NewGuid().ToString();

                                        using (ThreadLock.Lock(myConnectedClients))
                                        {
                                            if (!myConnectedClients.ContainsKey(aClientId))
                                            {
                                                myConnectedClients[aClientId] = aClientContext;
                                            }
                                            else
                                            {
                                                // Note: if the client id already exists then the connection cannot be open
                                                //       and the connection with this  client will be closed.
                                                EneterTrace.Warning(TracedObject + "could not open connection for client '" + aClientId + "' because the client with same id is already connected.");
                                                break;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        EneterTrace.Warning(TracedObject + "the client '" + aClientId + "' has already open connection.");
                                    }
                                }

                                // Notify message.
                                // Ensure that nobody will try to use id of somebody else.
                                aMessageContext.ProtocolMessage.ResponseReceiverId = aClientId;
                                NotifyMessageContext(aMessageContext);
                            }
                            else if (aProtocolMessage == null)
                            {
                                // Client disconnected. Or the client shall be disconnected because of incorrect message format.
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                finally
                {
                    // Remove client from connected clients.
                    if (aClientId != null)
                    {
                        using (ThreadLock.Lock(myConnectedClients))
                        {
                            myConnectedClients.Remove(aClientId);
                        }
                    }

                    // If the disconnection does not come from the service
                    // and the client was successfuly connected then notify about the disconnection.
                    if (!aClientContext.IsClosedFromService && aClientId != null)
                    {
                        ProtocolMessage aCloseProtocolMessage = new ProtocolMessage(EProtocolMessageType.CloseConnectionRequest, aClientId, null);
                        MessageContext  aMessageContext       = new MessageContext(aCloseProtocolMessage, aClientIp);

                        // Notify duplex input channel about the disconnection.
                        NotifyMessageContext(aMessageContext);
                    }

                    client.CloseConnection();
                }
            }
        }