コード例 #1
0
        private async Task WriteProcessorResponseAsync(Rs2LoginResponse loginResult, IChannelHandlerContext ctx, IsaacRandomPair randomPair)
        {
            try
            {
                await ctx.WriteAndFlushAsync(loginResult);

                HandleLoginProcessorResponse(loginResult.Player, loginResult.Status, ctx, randomPair);
            }
            catch (Exception e)
            {
                Log.Logger.Error(e, nameof(WriteProcessorResponseAsync));
                await ctx.CloseAsync();
            }
        }
コード例 #2
0
        private void HandleLoginProcessorResponse(Player player, LoginStatus response, IChannelHandlerContext ctx, IsaacRandomPair randomPair)
        {
            if (response != LoginStatus.StatusOk)
            {
                ctx.CloseAsync();
            }
            else
            {
                if (player == null)
                {
                    ctx.CloseAsync();
                    throw new InvalidOperationException("Cannot initialize player is null");
                }

                ctx.Channel.Pipeline.Remove(nameof(LoginEncoder));
                ctx.Channel.Pipeline.Remove(nameof(LoginDecoder));
                var gameMessageHandlers = _gameMessageProvider.Provide();

                foreach (var gameMessageHandler in gameMessageHandlers)
                {
                    if (gameMessageHandler is ICipherAwareHandler)
                    {
                        ((ICipherAwareHandler)gameMessageHandler).CipherPair = randomPair;
                    }

                    if (gameMessageHandler is IPlayerAwareHandler)
                    {
                        ((IPlayerAwareHandler)gameMessageHandler).Player = player;
                    }
                }
                ctx.Channel.Pipeline.AddLast(gameMessageHandlers);
                ctx.GetAttribute(Constants.PlayerAttributeKey).SetIfAbsent(player);
                player.ChannelHandlerContext = ctx;
                _world.Add(player);
                if (!_reconnecting)
                {
                    _ = _playerInitializer.InitializeAsync(player);
                }
                else
                {
                    player.UpdateAppearance();
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Decodes the payload state.
        /// </summary>
        /// <param name="ctx">The ctx.</param>
        /// <param name="buffer">The buffer.</param>
        /// <param name="output">The output.</param>
        private void DecodePayload(IChannelHandlerContext ctx, IByteBuffer buffer, List <object> output)
        {
            if (buffer.ReadableBytes >= _loginLength)
            {
                IByteBuffer payload = buffer.ReadBytes(_loginLength);
                var         version = 255 - payload.ReadByte();

                var release = payload.ReadShort();

                var memoryStatus = payload.ReadByte();
                if (memoryStatus != 0 && memoryStatus != 1)
                {
                    _logger.Information("Login memoryStatus ({0}) not in expected range of [0, 1].", memoryStatus);
                    WriteResponseCode(ctx, LoginStatus.StatusLoginServerRejectedSession);
                    return;
                }

                var lowMemory = memoryStatus == 1;

                var crcs = new int[Constants.ArchiveCount];
                for (var index = 0; index < Constants.ArchiveCount; index++)
                {
                    crcs[index] = payload.ReadInt();
                }

                var length = payload.ReadByte();
                if (length != _loginLength - 41)
                {
                    _logger.Information("Login packet unexpected length ({0})", length);
                    WriteResponseCode(ctx, LoginStatus.StatusLoginServerRejectedSession);
                    return;
                }

                /*
                 * var secureBytes = payload.ReadBytes(length);
                 * var value = new BigInteger(secureBytes.Array.Take(length).ToArray());
                 *
                 * RSA?
                 * value = BigInteger.ModPow(value, Constants.RSA_MODULUS, Constants.RSA_EXPONENT);
                 * var secureBuffer = Unpooled.WrappedBuffer(value.ToByteArray());
                 */


                var id = payload.ReadByte();
                if (id != 10)
                {
                    _logger.Information("Unable to read id from secure payload.");
                    WriteResponseCode(ctx, LoginStatus.StatusLoginServerRejectedSession);
                    return;
                }


                var clientSeed   = payload.ReadLong();
                var reportedSeed = payload.ReadLong();
                if (reportedSeed != _serverSeed)
                {
                    _logger.Information("Reported seed differed from server seed.");
                    WriteResponseCode(ctx, LoginStatus.StatusLoginServerRejectedSession);
                    return;
                }

                var uid           = payload.ReadInt();
                var username      = payload.ReadString();
                var password      = payload.ReadString();
                var socketAddress = (IPEndPoint)ctx.Channel.RemoteAddress;
                var hostAddress   = socketAddress.Address.ToString();

                var seed = new int[4];
                seed[0] = (int)(clientSeed >> 32);
                seed[1] = (int)clientSeed;
                seed[2] = (int)(_serverSeed >> 32);
                seed[3] = (int)_serverSeed;

                var decodingRandom = new IsaacRandom(seed);
                for (int index = 0; index < seed.Length; index++)
                {
                    seed[index] += 50;
                }

                var encodingRandom = new IsaacRandom(seed);

                var credentials = new PlayerCredentials
                {
                    Username        = username,
                    Password        = password,
                    EncodedUsername = _usernameHash,
                    Uid             = uid,
                    HostAddress     = hostAddress,
                };

                var randomPair = new IsaacRandomPair(encodingRandom, decodingRandom);
                var request    = new Rs2LoginRequest
                {
                    Credentials   = credentials,
                    RandomPair    = randomPair,
                    Reconnecting  = _reconnecting,
                    LowMemory     = lowMemory,
                    ReleaseNumber = release,
                    ArchiveCrcs   = crcs,
                    ClientVersion = version,
                    OnResult      = (loginTask) => WriteProcessorResponseAsync(loginTask, ctx, randomPair)
                };

                _loginProcessor.Enqueue(request);
            }
        }