// access the websocket data as a string; (if you JSON serialized, you might want to only override this function
        // because you'll know that all of your data will be a string that you are going to deserialize;
        // If you wanted to do something like streaming video via direct byte arrays, you'd want to override the other
        // "receive" function.
        public virtual async Task ReceiveMessageString(string sessionKey, WebsocketSessionPeer peer, WebSocketReceiveResult result, string socketMessage)
        {
            try
            {
                // parse the request to access the data;
                WebsocketSessionMessageRequest messageRequest = System.Text.Json.JsonSerializer.Deserialize <WebsocketSessionMessageRequest>(socketMessage);
                if (messageRequest.Type == WebsocketSessionMessageType.Unknown)
                {
                    messageRequest.Type = WebsocketSessionMessageType.Text;
                }

                // process the request and send the response message, if applicable;
                ProcessMessageRequest(messageRequest, sessionKey, peer);
            }
            catch (Exception exception)
            {
                WebsocketSessionError error = new WebsocketSessionError()
                {
                    ErrorCode = "WP_002", Message = "An error occurred while processing the message"
                };
                SendMessage(peer.Socket, error);
            }
        }
        private Task ProcessMessageRequest(WebsocketSessionMessageRequest request, string sessionKey, WebsocketSessionPeer peer)
        {
            // get a reference to the session
            WebsocketSession session = GetSessionByKey(sessionKey);

            // handle the different types of messages;
            string message = "";

            switch (request.Type)
            {
            case WebsocketSessionMessageType.Introduction:
                string hostId = session.GetAttributeValue <string>("hostId");
                WebsocketSessionPeerToken token = System.Text.Json.JsonSerializer.Deserialize <Models.WebsocketSessionPeerToken>(request.Message);
                peer.Token.DisplayName = token.DisplayName;
                peer.Token.IconUrl     = token.IconUrl;

                if (token.PeerId == hostId)
                {
                    // if host, no need to request access; just grant access;
                    WebsocketSessionUpdate[]        updates           = CreatePeerUpdates(WebsocketSessionUpdateStatus.AccessGranted, peer.Token);
                    WebsocketSessionMessageResponse hostAlertResponse = CreateWebsocketResponseMessage(WebsocketSessionMessageType.StatusUpdates, updates);
                    SendMessage(sessionKey, hostId, hostAlertResponse);
                    return(Task.CompletedTask);
                }
                message = request.Message;
                break;

            case WebsocketSessionMessageType.StatusUpdates:
            case WebsocketSessionMessageType.ByteArray:
            case WebsocketSessionMessageType.Text:
                message = request.Message;
                break;

            case WebsocketSessionMessageType.Reaction:
                if (request.TargetMessageId == null)
                {
                    throw new Exception("Reaction must provide TargetMessageId value.");
                }
                break;

            default:
                throw new Exception("Unknown Message Type: " + request.Type);
            }

            List <WebsocketSessionMessageResponse> messages = session.GetAttributeValue <List <WebsocketSessionMessageResponse> >("messages");

            WebsocketSessionMessageResponse messageResponse = new WebsocketSessionMessageResponse()
            {
                MessageId   = messages.Count,
                MessageType = request.Type,
                Message     = message,
                SenderId    = peer.Token.PeerId,
                Recipients  = request.Recipients
            };

            messages.Add(messageResponse);

            if (request.Recipients == null || request.Recipients.Length == 0)
            {
                SendMessageToPeers(sessionKey, peer.Token.PeerId, messageResponse);
            }
            else
            {
                SendMessage(sessionKey, request.Recipients, messageResponse);
            }
            return(Task.CompletedTask);
        }