Experimental collection of id/access_hash pairs

This commit is contained in:
Wizou 2021-08-30 01:31:08 +02:00
parent 0d5546bee5
commit 4174b21a83
3 changed files with 47 additions and 11 deletions

View file

@ -307,7 +307,7 @@ namespace WTelegram
throw new ApplicationException($"Received a packet encrypted with unexpected key {authKeyId:X}");
if (authKeyId == 0) // Unencrypted message
{
using var reader = new BinaryReader(new MemoryStream(data, 8, data.Length - 8));
using var reader = new TL.BinaryReader(new MemoryStream(data, 8, data.Length - 8), this);
long msgId = _lastRecvMsgId = reader.ReadInt64();
if ((msgId & 1) == 0) throw new ApplicationException($"Invalid server msgId {msgId}");
int length = reader.ReadInt32();
@ -327,7 +327,7 @@ namespace WTelegram
byte[] decrypted_data = EncryptDecryptMessage(data.AsSpan(24), false, _session.AuthKey, msgKeyLarge);
if (decrypted_data.Length < 36) // header below+ctorNb
throw new ApplicationException($"Decrypted packet too small: {decrypted_data.Length}");
using var reader = new BinaryReader(new MemoryStream(decrypted_data));
using var reader = new TL.BinaryReader(new MemoryStream(decrypted_data), this);
var serverSalt = reader.ReadInt64(); // int64 salt
var sessionId = reader.ReadInt64(); // int64 session_id
var msgId = _lastRecvMsgId = reader.ReadInt64();// int64 message_id
@ -385,7 +385,7 @@ namespace WTelegram
};
}
internal MsgContainer ReadMsgContainer(BinaryReader reader)
internal MsgContainer ReadMsgContainer(TL.BinaryReader reader)
{
int count = reader.ReadInt32();
var array = new _Message[count];
@ -422,7 +422,7 @@ namespace WTelegram
return new MsgContainer { messages = array };
}
private RpcResult ReadRpcResult(BinaryReader reader)
private RpcResult ReadRpcResult(TL.BinaryReader reader)
{
long msgId = reader.ReadInt64();
var (type, tcs) = PullPendingRequest(msgId);
@ -838,5 +838,34 @@ namespace WTelegram
reply_to_msg_id: reply_to_msg_id, entities: entities, schedule_date: schedule_date);
}
#endregion
/// <summary>Enable the collection of id/access_hash pairs (experimental)</summary>
public bool CollectAccessHash { get; set; }
readonly Dictionary<Type, Dictionary<long, long>> _accessHashes = new();
public IEnumerable<KeyValuePair<long, long>> AllAccessHashesFor<T>() where T : ITLObject
=> _accessHashes.GetValueOrDefault(typeof(T));
/// <summary>Retrieve the access_hash associated with this id (for a TL class)</summary>
/// <typeparam name="T">a TL object class. For example User, Channel or Photo</typeparam>
public long? GetAccessHashFor<T>(long id) where T : ITLObject
{
lock (_accessHashes)
return _accessHashes.GetOrCreate(typeof(T)).TryGetValue(id, out var access_hash) ? access_hash : null;
}
public void SetAccessHashFor<T>(long id, long access_hash) where T : ITLObject
{
lock (_accessHashes)
_accessHashes.GetOrCreate(typeof(T))[id] = access_hash;
}
internal void UpdateAccessHash(object obj, Type type, object access_hash)
{
if (!CollectAccessHash) return;
if (access_hash is not long accessHash) return;
if (type.GetField("id") is not FieldInfo idField) return;
if (idField.GetValue(obj) is not long id)
if (idField.GetValue(obj) is not int idInt) return;
else id = idInt;
lock (_accessHashes)
_accessHashes.GetOrCreate(type)[id] = accessHash;
}
}
}

View file

@ -109,7 +109,7 @@ namespace WTelegram
var (tmp_aes_key, tmp_aes_iv) = ConstructTmpAESKeyIV(resPQ.server_nonce, pqInnerData.new_nonce);
var answer = AES_IGE_EncryptDecrypt(serverDHparamsOk.encrypted_answer, tmp_aes_key, tmp_aes_iv, false);
using var encryptedReader = new BinaryReader(new MemoryStream(answer));
using var encryptedReader = new TL.BinaryReader(new MemoryStream(answer), client);
var answerHash = encryptedReader.ReadBytes(20);
var answerObj = encryptedReader.ReadTLObject();
if (answerObj is not ServerDHInnerData serverDHinnerData) throw new ApplicationException("not server_DH_inner_data");

View file

@ -24,7 +24,7 @@ namespace TL
internal static T Deserialize<T>(byte[] bytes) where T : ITLObject
{
using var memStream = new MemoryStream(bytes);
using var reader = new BinaryReader(memStream);
using var reader = new BinaryReader(memStream, null);
return (T)reader.ReadTLObject();
}
@ -56,7 +56,7 @@ namespace TL
if (!Table.TryGetValue(ctorNb, out var type))
throw new ApplicationException($"Cannot find type for ctor #{ctorNb:x}");
var obj = Activator.CreateInstance(type);
var fields = obj.GetType().GetFields().GroupBy(f => f.DeclaringType).Reverse().SelectMany(g => g);
var fields = type.GetFields().GroupBy(f => f.DeclaringType).Reverse().SelectMany(g => g);
int flags = 0;
IfFlagAttribute ifFlag;
foreach (var field in fields)
@ -64,9 +64,10 @@ namespace TL
if (((ifFlag = field.GetCustomAttribute<IfFlagAttribute>()) != null) && (flags & (1 << ifFlag.Bit)) == 0) continue;
object value = reader.ReadTLValue(field.FieldType);
field.SetValue(obj, value);
if (field.Name.Equals("Flags", StringComparison.OrdinalIgnoreCase)) flags = (int)value;
if (field.Name == "flags") flags = (int)value;
else if (field.Name == "access_hash") reader.Client?.UpdateAccessHash(obj, type, value);
}
return type == typeof(GzipPacked) ? UnzipPacket((GzipPacked)obj) : (ITLObject)obj;
return type == typeof(GzipPacked) ? UnzipPacket((GzipPacked)obj, reader.Client) : (ITLObject)obj;
}
internal static void WriteTLValue(this BinaryWriter writer, object value)
@ -220,9 +221,9 @@ namespace TL
writer.Write(0); // null arrays are serialized as empty
}
internal static ITLObject UnzipPacket(GzipPacked obj)
internal static ITLObject UnzipPacket(GzipPacked obj, WTelegram.Client client)
{
using var reader = new BinaryReader(new GZipStream(new MemoryStream(obj.packed_data), CompressionMode.Decompress));
using var reader = new BinaryReader(new GZipStream(new MemoryStream(obj.packed_data), CompressionMode.Decompress), client);
var result = reader.ReadTLObject();
return result;
}
@ -234,6 +235,12 @@ namespace TL
#endif
}
public class BinaryReader : System.IO.BinaryReader
{
public readonly WTelegram.Client Client;
public BinaryReader(Stream stream, WTelegram.Client client) : base(stream) => Client = client;
}
[AttributeUsage(AttributeTargets.Class)]
public class TLDefAttribute : Attribute
{