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