Inheritance: Framework.Network.SessionBase, IDisposable
        // TODO: Verify ClientRequest values.
        static async Task HandleRealmListTicketRequest(ClientRequest clientRequest, BnetSession session)
        {
            var paramIdentityValue = clientRequest.GetVariant("Param_Identity")?.BlobValue.ToStringUtf8();
            var paramClientInfoValue = clientRequest.GetVariant("Param_ClientInfo")?.BlobValue.ToStringUtf8();

            if (paramIdentityValue != null && paramClientInfoValue != null)
            {
                var realmListTicketIdentity = CreateObject<RealmListTicketIdentity>(paramIdentityValue, true);
                var realmListTicketClientInformation = CreateObject<RealmListTicketClientInformation>(paramClientInfoValue, true);

                session.GameAccount = session.Account.GameAccounts.SingleOrDefault(ga => ga.Id == realmListTicketIdentity.GameAccountId);

                if (session.GameAccount != null)
                {
                    session.RealmListSecret = realmListTicketClientInformation.Info.Secret.Select(x => Convert.ToByte(x)).ToArray();
                    session.RealmListTicket = new byte[0].GenerateRandomKey(32);

                    var realmListTicketResponse = new ClientResponse();

                    realmListTicketResponse.Attribute.Add(new Bgs.Protocol.Attribute
                    {
                        Name = "Param_RealmListTicket",
                        Value = new Variant
                        {
                            BlobValue = ByteString.CopyFrom(session.RealmListTicket)
                        }
                    });

                    await session.Send(realmListTicketResponse);
                }
            }
            else
                session.Dispose();
        }
        public static async void HandleVerifyWebCredentialsRequest(VerifyWebCredentialsRequest verifyWebCredentials, BnetSession session)
        {
            var logonResult = new LogonResult();

            if (verifyWebCredentials.WebCredentials.ToStringUtf8() == session.LoginTicket)
            {
                logonResult.AccountId = new EntityId
                {
                    High = 0x100000000000000,
                    Low = session.Account.Id
                };

                session.Account.GameAccounts.ForEach(ga =>
                {
                    logonResult.GameAccountId.Add(new EntityId
                    {
                        // TODO: Build the right High value.
                        High = 0x200000200576F57,
                        Low = ga.Id
                    });
                });

                logonResult.SessionKey = ByteString.CopyFromUtf8(new byte[0].GenerateRandomKey(64).ToHexString());
            }
            else
                logonResult.ErrorCode = (uint)BnetErrorCode.Denied;

            await session.Send(logonResult, BnetServiceHash.AuthenticationListenerService, 5);
        }
        public static async void HandleDisconnectRequest(DisconnectRequest disconnectRequest, BnetSession session)
        {
            Log.Message(LogTypes.Info, $"Client '{session.GetClientInfo()} disconnected ({disconnectRequest.ErrorCode}).");

            await session.Send(new DisconnectNotification
            {
                ErrorCode = disconnectRequest.ErrorCode,
            }, BnetServiceHash.ConnectionService, 4);
        }
        public static async void HandleClientRequest(ClientRequest clientRequest, BnetSession session)
        {
            Func<ClientRequest, BnetSession, Task> clientRequestHandler;

            if (clientRequestHandlers.TryGetValue(clientRequest.Attribute[0].Name, out clientRequestHandler))
            {
                Log.Message(LogTypes.Error, $"client request '{clientRequest}'.\n");

                await clientRequestHandler(clientRequest, session);
            }
            else
                Log.Message(LogTypes.Error, $"Tried to call non existing handler for client request '{clientRequest.Attribute[0].Name}'.");
        }
        public static async void HandleLogonRequest(LogonRequest logonRequest, BnetSession session)
        {
            // TODO: Implement version checks, etc.
            //if (DB.Auth.Any<Application>(a => a.Program == logonRequest.Program))
            {
                var challengeExternalRequest = new ChallengeExternalRequest
                {
                    PayloadType = "web_auth_url",
                    Payload = ByteString.CopyFromUtf8($"https://{BnetConfig.BnetChallengeHost}:{BnetConfig.BnetChallengeBindPort}/login/{session.Guid}")
                };

                await session.Send(challengeExternalRequest, BnetServiceHash.AuthenticationClientService, 3);
            }
        }
        public static async void HandleConnectRequest(ConnectRequest connectRequest, BnetSession session)
        {
            // TODO: Verify sent values.
            await session.Send(new ConnectResponse
            {
                ClientId = connectRequest.ClientId,
                UseBindlessRpc = connectRequest.UseBindlessRpc,

                ServerTime = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds(),
                ServerId = new ProcessId
                {
                    Epoch = 0,
                    Label = 0
                }
            });
        }
        // TODO: Implement loading existing realms.
        // TODO: Implement existing character counts.
        static async Task HandleRealmListRequest(ClientRequest clientRequest, BnetSession session)
        {
            var realmJoinRequest = clientRequest.GetVariant("Command_RealmListRequest_v1_b9")?.StringValue;
            var realmListTicket = clientRequest.GetVariant("Param_RealmListTicket")?.BlobValue.ToByteArray();

            if (session.RealmListTicket.Compare(realmListTicket))
            {
                var realmListResponse = new ClientResponse();
                var realmlist = new RealmListUpdates();

                realmListResponse.Attribute.Add(new Bgs.Protocol.Attribute
                {
                    Name = "Param_RealmList",
                    Value = new Variant
                    {
                        BlobValue = ByteString.CopyFrom(Deflate("JSONRealmListUpdates", realmlist))
                    }
                });

                var realmCharacterCountList = new RealmCharacterCountList();

                realmListResponse.Attribute.Add(new Bgs.Protocol.Attribute
                {
                    Name = "Param_CharacterCountList",
                    Value = new Variant
                    {
                        BlobValue = ByteString.CopyFrom(Deflate("JSONRealmCharacterCountList", realmCharacterCountList))
                    }
                });

                await session.Send(realmListResponse);
            }
        }
        // TODO: Implement.
        static Task HandleLastCharPlayedRequest(ClientRequest clientRequest, BnetSession session)
        {
            var lastCharPlayedResponse = new ClientResponse();

            return session.Send(lastCharPlayedResponse);
        }
        public static async void HandleGetAllValuesForAttributeRequest(GetAllValuesForAttributeRequest getAllValuesForAttributeRequest, BnetSession session)
        {
            if (getAllValuesForAttributeRequest.AttributeKey == "Command_RealmListRequest_v1_b9")
            {
                var getAllValuesForAttributeResponse = new GetAllValuesForAttributeResponse();

                getAllValuesForAttributeResponse.AttributeValue.Add(new Variant { StringValue = "0-0-0" });

                await session.Send(getAllValuesForAttributeResponse);
            }
        }
        // TODO: Implement realm join function.
        static async Task HandleRealmJoinRequest(ClientRequest clientRequest, BnetSession session)
        {
            var realmJoinRequest = clientRequest.GetVariant("Command_RealmJoinRequest_v1_b9")?.StringValue;
            var realmAddress = clientRequest.GetVariant("Param_RealmAddress")?.UintValue;
            var realmListTicket = clientRequest.GetVariant("Param_RealmListTicket")?.BlobValue.ToByteArray();
            var bnetSessionKey = clientRequest.GetVariant("Param_BnetSessionKey")?.BlobValue.ToByteArray();

            // Check for valid realmlist ticket.
            if (realmListTicket.Compare(session.RealmListTicket))
            {
                var realmJoinResponse = new ClientResponse();

                await session.Send(realmJoinResponse);
            }
        }
 public static async void HandlePing(NoData noData, BnetSession session)
 {
     await session.Send(new NoData(), BnetServiceHash.ConnectionService, 5);
 }