fix #27: compatibility with Mono/Android

This commit is contained in:
Wizou 2022-02-04 02:51:14 +01:00
parent 72fba55407
commit 1b1243a758
5 changed files with 319 additions and 312 deletions

View file

@ -369,7 +369,7 @@ namespace WTelegram
{ {
lock (_session) _session.Save(); lock (_session) _session.Save();
} }
Helpers.Log(2, $"Connected to {(TLConfig.test_mode ? "Test DC" : "DC")} {TLConfig.this_dc}... {TLConfig.flags & (Config.Flags)~0xE00}"); Helpers.Log(2, $"Connected to {(TLConfig.test_mode ? "Test DC" : "DC")} {TLConfig.this_dc}... {TLConfig.flags & (Config.Flags)~0xE00U}");
} }
/// <summary>Obtain/create a Client for a secondary session on a specific Data Center</summary> /// <summary>Obtain/create a Client for a secondary session on a specific Data Center</summary>

View file

@ -39,6 +39,7 @@ namespace WTelegram
private readonly DateTime _sessionStart = DateTime.UtcNow; private readonly DateTime _sessionStart = DateTime.UtcNow;
private readonly SHA256 _sha256 = SHA256.Create(); private readonly SHA256 _sha256 = SHA256.Create();
private Stream _store; private Stream _store;
private byte[] _reuseKey; // used only if AES Encryptor.CanReuseTransform = false (Mono)
private byte[] _encrypted = new byte[16]; private byte[] _encrypted = new byte[16];
private ICryptoTransform _encryptor; private ICryptoTransform _encryptor;
private Utf8JsonWriter _jsonWriter; private Utf8JsonWriter _jsonWriter;
@ -83,6 +84,7 @@ namespace WTelegram
session._store = store; session._store = store;
Encryption.RNG.GetBytes(session._encrypted, 0, 16); Encryption.RNG.GetBytes(session._encrypted, 0, 16);
session._encryptor = aes.CreateEncryptor(rgbKey, session._encrypted); session._encryptor = aes.CreateEncryptor(rgbKey, session._encrypted);
if (!session._encryptor.CanReuseTransform) session._reuseKey = rgbKey;
session._jsonWriter = new Utf8JsonWriter(session._jsonStream, default); session._jsonWriter = new Utf8JsonWriter(session._jsonStream, default);
return session; return session;
} }
@ -98,6 +100,9 @@ namespace WTelegram
_encryptor.TransformBlock(_sha256.ComputeHash(utf8Json, 0, utf8JsonLen), 0, 32, _encrypted, 16); _encryptor.TransformBlock(_sha256.ComputeHash(utf8Json, 0, utf8JsonLen), 0, 32, _encrypted, 16);
_encryptor.TransformBlock(utf8Json, 0, encryptedLen - 64, _encrypted, 48); _encryptor.TransformBlock(utf8Json, 0, encryptedLen - 64, _encrypted, 48);
_encryptor.TransformFinalBlock(utf8Json, encryptedLen - 64, utf8JsonLen & 15).CopyTo(_encrypted, encryptedLen - 16); _encryptor.TransformFinalBlock(utf8Json, encryptedLen - 64, utf8JsonLen & 15).CopyTo(_encrypted, encryptedLen - 16);
if (!_encryptor.CanReuseTransform) // under Mono, AES encryptor is not reusable
using (var aes = Aes.Create())
_encryptor = aes.CreateEncryptor(_reuseKey, _encrypted[0..16]);
_store.Position = 0; _store.Position = 0;
_store.Write(_encrypted, 0, encryptedLen); _store.Write(_encrypted, 0, encryptedLen);
_store.SetLength(encryptedLen); _store.SetLength(encryptedLen);

File diff suppressed because it is too large Load diff

View file

@ -363,7 +363,7 @@ namespace TL
/// <summary>Random message ID of the message this message replies to (parameter added in layer 45)</summary> /// <summary>Random message ID of the message this message replies to (parameter added in layer 45)</summary>
[IfFlag(3)] public long reply_to_random_id; [IfFlag(3)] public long reply_to_random_id;
[Flags] public enum Flags [Flags] public enum Flags : uint
{ {
/// <summary>Field <see cref="reply_to_random_id"/> has a value</summary> /// <summary>Field <see cref="reply_to_random_id"/> has a value</summary>
has_reply_to_random_id = 0x8, has_reply_to_random_id = 0x8,
@ -503,7 +503,7 @@ namespace TL
/// <summary>Random group ID, assigned by the author of message.<br/>Multiple encrypted messages with a photo attached and with the same group ID indicate an <a href="https://corefork.telegram.org/api/files#albums-grouped-media">album or grouped media</a> (parameter added in layer 45)</summary> /// <summary>Random group ID, assigned by the author of message.<br/>Multiple encrypted messages with a photo attached and with the same group ID indicate an <a href="https://corefork.telegram.org/api/files#albums-grouped-media">album or grouped media</a> (parameter added in layer 45)</summary>
[IfFlag(17)] public long grouped_id; [IfFlag(17)] public long grouped_id;
[Flags] public enum Flags [Flags] public enum Flags : uint
{ {
/// <summary>Field <see cref="reply_to_random_id"/> has a value</summary> /// <summary>Field <see cref="reply_to_random_id"/> has a value</summary>
has_reply_to_random_id = 0x8, has_reply_to_random_id = 0x8,

View file

@ -39,14 +39,14 @@ namespace TL
writer.Write(ctorNb); writer.Write(ctorNb);
IEnumerable<FieldInfo> fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); IEnumerable<FieldInfo> fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (tlDef.inheritBefore) fields = fields.GroupBy(f => f.DeclaringType).Reverse().SelectMany(g => g); if (tlDef.inheritBefore) fields = fields.GroupBy(f => f.DeclaringType).Reverse().SelectMany(g => g);
int flags = 0; uint flags = 0;
IfFlagAttribute ifFlag; IfFlagAttribute ifFlag;
foreach (var field in fields) foreach (var field in fields)
{ {
if (((ifFlag = field.GetCustomAttribute<IfFlagAttribute>()) != null) && (flags & (1 << ifFlag.Bit)) == 0) continue; if (((ifFlag = field.GetCustomAttribute<IfFlagAttribute>()) != null) && (flags & (1U << ifFlag.Bit)) == 0) continue;
object value = field.GetValue(obj); object value = field.GetValue(obj);
writer.WriteTLValue(value, field.FieldType); writer.WriteTLValue(value, field.FieldType);
if (field.Name == "flags") flags = (int)value; if (field.Name == "flags") flags = (uint)value;
} }
} }
@ -63,14 +63,14 @@ namespace TL
var obj = Activator.CreateInstance(type); var obj = Activator.CreateInstance(type);
IEnumerable<FieldInfo> fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); IEnumerable<FieldInfo> fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (tlDef.inheritBefore) fields = fields.GroupBy(f => f.DeclaringType).Reverse().SelectMany(g => g); if (tlDef.inheritBefore) fields = fields.GroupBy(f => f.DeclaringType).Reverse().SelectMany(g => g);
int flags = 0; uint flags = 0;
IfFlagAttribute ifFlag; IfFlagAttribute ifFlag;
foreach (var field in fields) foreach (var field in fields)
{ {
if (((ifFlag = field.GetCustomAttribute<IfFlagAttribute>()) != null) && (flags & (1 << ifFlag.Bit)) == 0) continue; if (((ifFlag = field.GetCustomAttribute<IfFlagAttribute>()) != null) && (flags & (1U << ifFlag.Bit)) == 0) continue;
object value = reader.ReadTLValue(field.FieldType); object value = reader.ReadTLValue(field.FieldType);
field.SetValue(obj, value); field.SetValue(obj, value);
if (field.Name == "flags") flags = (int)value; if (field.Name == "flags") flags = (uint)value;
else if (field.Name == "access_hash") reader.Client?.UpdateAccessHash(obj, type, value); else if (field.Name == "access_hash") reader.Client?.UpdateAccessHash(obj, type, value);
} }
return (IObject)obj; return (IObject)obj;
@ -108,6 +108,8 @@ namespace TL
writer.Write(int256); writer.Write(int256);
else if (value is IObject tlObject) else if (value is IObject tlObject)
WriteTLObject(writer, tlObject); WriteTLObject(writer, tlObject);
else if (type.IsEnum) // needed for Mono (enums in generic types are seen as TypeCode.Object)
writer.Write((uint)value);
else else
ShouldntBeHere(); ShouldntBeHere();
break; break;