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);
            }
        }
        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();
                }
            }
        }