Ctrl K
ComunidadGuías…

Ferrite.Core/RequestChain/AuthKeyProcessor.cs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2022-2026 Aykut Alparslan KOC

using Ferrite.Core.Connection;
using Ferrite.Core.Execution;
using Ferrite.Services.Sessions;
using Ferrite.TL;
using Ferrite.TL.mtproto;
using Ferrite.Utils;
using ReqPqMulti = Ferrite.TL.mtproto.ReqPqMulti;

namespace Ferrite.Core.RequestChain;

public class AuthKeyProcessor : ILinkedHandler
{
    private readonly ISessionService _sessionManager;
    private readonly ILogger _log;
    private readonly IExecutionEngine _api;
    public AuthKeyProcessor(ISessionService sessionManager, ILogger log, IExecutionEngine api)
    {
        _sessionManager = sessionManager;
        _log = log;
        _api = api;
    }

    public ILinkedHandler? Next { get; set; }

    public ILinkedHandler SetNext(ILinkedHandler value)
    {
        Next = value;
        return Next;
    }

    public async ValueTask Process(object? sender, TLBytes input, TLExecutionContext ctx)
    {
        var constructor = input.Constructor;
        if (constructor == Constructors.mtproto_ReqPqMulti &&
            sender is MTProtoConnection connection)
        {
            try
            {
                var result = await _api.Invoke(input, ctx);
                if (result == null) return;
                using var response = result.Value;

                Services.Transport.MTProtoMessage message = new Services.Transport.MTProtoMessage();
                message.SessionId = ctx.SessionId;
                message.IsResponse = true;
                message.IsContentRelated = true;
                message.Data = response.AsSpan().ToArray();
                var nonce = new ReqPqMulti(input.AsSpan()).Nonce.ToArray();
                await _sessionManager.AddAuthSessionAsync(nonce,
                    AuthSessionState.FromSessionData(_sessionManager.NodeId,
                        ctx.SessionData),
                    new ActiveSession(connection));
                message.Nonce = nonce;
                message.MessageType = MTProtoMessageType.Unencrypted;
                await connection.SendAsync(message);

                _log.Information("Result for req_pq_multi sent.");
            }
            finally
            {
                input.Dispose();
            }
        }
        else if (constructor == Constructors.mtproto_ReqDhParams)
        {
            try
            {
                var nonce = new TL.mtproto.ReqDhParams(input.AsSpan()).Nonce.ToArray();
                var state = await _sessionManager.GetAuthSessionStateAsync(nonce);
                if (state == null) return;

                RestoreMissingSessionData(ctx, state);
                var result = await _api.Invoke(input, ctx);
                if (result == null) return;
                using var response = result.Value;

                Services.Transport.MTProtoMessage message = new Services.Transport.MTProtoMessage();
                message.SessionId = ctx.SessionId;
                message.IsResponse = true;
                message.IsContentRelated = true;
                message.Data = response.AsSpan().ToArray();
                message.MessageType = MTProtoMessageType.Unencrypted;
                message.Nonce = nonce;

                await _sessionManager.UpdateAuthSessionAsync(nonce,
                    AuthSessionState.FromSessionData(_sessionManager.NodeId,
                        ctx.SessionData));
                if (sender is MTProtoConnection dhConnection)
                {
                    await dhConnection.SendAsync(message);
                }

                _log.Information("Result for req_DH_params sent.");
            }
            finally
            {
                input.Dispose();
            }
        }
        else if (constructor == Constructors.mtproto_SetClientDhParams)
        {
            try
            {
                var nonce = new TL.mtproto.SetClientDhParams(input.AsSpan()).Nonce.ToArray();
                var state = await _sessionManager.GetAuthSessionStateAsync(nonce);
                if (state == null) return;

                RestoreMissingSessionData(ctx, state);
                var result = await _api.Invoke(input, ctx);
                if (result == null) return;
                using var response = result.Value;

                MTProtoMessage message = new Services.Transport.MTProtoMessage();
                message.SessionId = ctx.SessionId;
                message.IsResponse = true;
                message.IsContentRelated = true;
                message.Data = response.AsSpan().ToArray();
                message.MessageType = MTProtoMessageType.Unencrypted;
                message.Nonce = nonce;
                await _sessionManager.UpdateAuthSessionAsync(nonce,
                    AuthSessionState.FromSessionData(_sessionManager.NodeId,
                        ctx.SessionData));
                if (sender is MTProtoConnection clientDhConnection)
                {
                    await clientDhConnection.SendAsync(message);
                }

                _log.Information("Result for set_client_DH_params sent.");
            }
            finally
            {
                input.Dispose();
            }
        }
        else
        {
            if (Next != null) await Next.Process(sender, input, ctx);
            else input.Dispose();
        }
    }

    public async ValueTask Process(object? sender, ITLStreamingObject input, TLExecutionContext ctx)
    {
        if (Next != null) await Next.Process(sender, input, ctx);
    }

    private static void RestoreMissingSessionData(TLExecutionContext context,
        AuthSessionState persisted)
    {
        persisted.RestoreInto(context.SessionData);
    }
}