Added logger system

This commit is contained in:
Wizou 2021-08-04 10:11:07 +02:00
parent 39b0a79f0f
commit 85a3ea997f
6 changed files with 45 additions and 29 deletions

View file

@ -74,7 +74,7 @@ namespace WTelegram
{
var endpoint = _session.DataCenter == null ? IPEndPoint.Parse(_config("server_address"))
: new IPEndPoint(IPAddress.Parse(_session.DataCenter.ip_address), _session.DataCenter.port);
Console.WriteLine($"Connecting to {endpoint}...");
Helpers.Log(2, $"Connecting to {endpoint}...");
_tcpClient = new TcpClient(endpoint.AddressFamily);
await _tcpClient.ConnectAsync(endpoint.Address, endpoint.Port);
_networkStream = _tcpClient.GetStream();
@ -102,7 +102,7 @@ namespace WTelegram
private async Task MigrateDCAsync(int dcId)
{
Console.WriteLine($"Migrate to DC {dcId}...");
Helpers.Log(2, $"Migrate to DC {dcId}...");
//TODO: Export/Import client authorization?
var prevFamily = _tcpClient.Client.RemoteEndPoint.AddressFamily;
_tcpClient.Close();
@ -137,7 +137,7 @@ namespace WTelegram
if (_session.AuthKeyID == 0) // send unencrypted message
{
Console.WriteLine($"Sending {msg.GetType().Name}...");
Helpers.Log(1, $"Sending {msg.GetType().Name}...");
writer.Write(0L); // int64 auth_key_id = 0 (Unencrypted)
writer.Write(msgId); // int64 message_id
writer.Write(0); // int32 message_data_length (to be patched)
@ -146,7 +146,7 @@ namespace WTelegram
}
else
{
Console.WriteLine($"Sending {msg.GetType().Name}... (seqno {seqno})");
Helpers.Log(1, $"Sending {msg.GetType().Name}... (seqno {seqno})");
//TODO: Implement MTProto 2.0
using var clearStream = new MemoryStream(1024); //TODO: choose a useful capacity
using var clearWriter = new BinaryWriter(clearStream, Encoding.UTF8);
@ -183,7 +183,7 @@ namespace WTelegram
_lastSentMsg = msg;
}
internal async Task<object> RecvInternalAsync()
internal async Task<ITLObject> RecvInternalAsync()
{
var data = await RecvFrameAsync();
if (data.Length == 4 && data[3] == 0xFF)
@ -204,7 +204,7 @@ namespace WTelegram
var ctorNb = reader.ReadUInt32();
if (!Schema.Mappings.TryGetValue(ctorNb, out var realType))
throw new ApplicationException($"Cannot find type for ctor #{ctorNb:x}");
Console.WriteLine($"Receiving {realType.Name,-50} timestamp={_session.MsgIdToStamp(msgId)} isResponse={(msgId & 2) != 0} unencrypted");
Helpers.Log(1, $"Receiving {realType.Name,-50} timestamp={_session.MsgIdToStamp(msgId)} isResponse={(msgId & 2) != 0} unencrypted");
return Schema.DeserializeObject(reader, realType);
}
else if (authKeyId != _session.AuthKeyID)
@ -234,7 +234,7 @@ namespace WTelegram
var ctorNb = reader.ReadUInt32();
if (!Schema.Mappings.TryGetValue(ctorNb, out var realType))
throw new ApplicationException($"Cannot find type for ctor #{ctorNb:x}");
Console.WriteLine($"Receiving {realType.Name,-50} timestamp={_session.MsgIdToStamp(msgId)} isResponse={(msgId & 2) != 0} {(seqno == -1 ? "clearText" : "isContent")}={(seqno & 1) != 0}");
Helpers.Log(1, $"Receiving {realType.Name,-50} timestamp={_session.MsgIdToStamp(msgId)} isResponse={(msgId & 2) != 0} {(seqno == -1 ? "clearText" : "isContent")}={(seqno & 1) != 0}");
if (realType == typeof(RpcResult))
return DeserializeRpcResult(reader); // hack necessary because some RPC return bare types like bool or int[]
else
@ -282,14 +282,14 @@ namespace WTelegram
}
}
private object DeserializeRpcResult(BinaryReader reader)
private RpcResult DeserializeRpcResult(BinaryReader reader)
{
long reqMsgId = reader.ReadInt64();
var rpcResult = new RpcResult { req_msg_id = reqMsgId };
if (reqMsgId == _session.LastSentMsgId)
rpcResult.result = Schema.DeserializeValue(reader, _lastRpcResultType);
else
rpcResult.result = Schema.Deserialize<object>(reader);
rpcResult.result = Schema.Deserialize<ITLObject>(reader);
return rpcResult;
}
@ -343,15 +343,14 @@ namespace WTelegram
await SendAsync(msgsAck, false);
}
private async Task HandleMessageAsync(object obj)
private async Task HandleMessageAsync(ITLObject obj)
{
switch (obj)
{
case MsgContainer container:
foreach (var msg in container.messages)
{
Console.Write($" → {msg.body?.GetType().Name}");
Console.WriteLine($"{new string(' ', Math.Max(0, 60 - Console.CursorLeft))} timestamp={_session.MsgIdToStamp(msg.msg_id)} isResponse={(msg.msg_id & 2) != 0} {(msg.seqno == -1 ? "clearText" : "isContent")}={(msg.seqno & 1) != 0}");
Helpers.Log(1, $" → {msg.body?.GetType().Name,-48} timestamp={_session.MsgIdToStamp(msg.msg_id)} isResponse={(msg.msg_id & 2) != 0} {(msg.seqno == -1 ? "clearText" : "isContent")}={(msg.seqno & 1) != 0}");
if ((msg.seqno & 1) != 0) lock (_msgsToAck) _msgsToAck.Add(msg.msg_id);
if (msg.body != null) await HandleMessageAsync(msg.body);
}
@ -362,14 +361,14 @@ namespace WTelegram
await SendAsync(_lastSentMsg);
break;
case BadMsgNotification badMsgNotification:
Console.WriteLine($"BadMsgNotification {badMsgNotification.error_code} for msg {badMsgNotification.bad_msg_seqno}");
Helpers.Log(3, $"BadMsgNotification {badMsgNotification.error_code} for msg {badMsgNotification.bad_msg_seqno}");
break;
case RpcResult rpcResult:
if (_session.MsgIdToStamp(rpcResult.req_msg_id) >= _session.SessionStart)
throw new ApplicationException($"Got RpcResult({rpcResult.result.GetType().Name}) for unknown msgId {rpcResult.req_msg_id}");
break; // silently ignore results for msg_id from previous sessions
default:
//_updateHandler?.Invoke(obj);
_updateHandler?.Invoke(obj);
break;
}
}
@ -386,7 +385,7 @@ namespace WTelegram
api_hash = _apiHash,
settings = settings ?? new()
});
Console.WriteLine($"A verification code has been sent via {sentCode.type.GetType().Name[17..]}");
Helpers.Log(3, $"A verification code has been sent via {sentCode.type.GetType().Name[17..]}");
var verification_code = _config("verification_code");
var authorization = await CallAsync(new Auth_SignIn
{

View file

@ -28,7 +28,7 @@ namespace WTelegram
if (resPQ.nonce != reqPQ.nonce) throw new ApplicationException("Nonce mismatch");
var fingerprint = resPQ.server_public_key_fingerprints.FirstOrDefault(PublicKeys.ContainsKey);
if (fingerprint == 0) throw new ApplicationException("Couldn't match any server_public_key_fingerprints");
Console.WriteLine($"Selected public key with fingerprint {fingerprint:X}");
Helpers.Log(2, $"Selected public key with fingerprint {fingerprint:X}");
//3)
long retry_id = 0;
ulong pq = Helpers.FromBigEndian(resPQ.pq);
@ -69,7 +69,7 @@ namespace WTelegram
var g_a = new BigInteger(serverDHinnerData.g_a, true, true);
var dh_prime = new BigInteger(serverDHinnerData.dh_prime, true, true);
ValidityChecks(dh_prime, serverDHinnerData.g);
Console.WriteLine($"Server time: {serverDHinnerData.server_time} UTC");
Helpers.Log(1, $"Server time: {serverDHinnerData.server_time} UTC");
session.ServerTicksOffset = (serverDHinnerData.server_time - localTime).Ticks;
//6)
@ -210,7 +210,7 @@ namespace WTelegram
var bareData = Schema.Serialize(publicKey).AsSpan(4); // bare serialization
var fingerprint = BitConverter.ToInt64(SHA1.HashData(bareData), 12); // 64 lower-order bits of SHA1
PublicKeys[fingerprint] = publicKey;
Console.WriteLine($"Loaded a public key with fingerprint {fingerprint:X}");
Helpers.Log(1, $"Loaded a public key with fingerprint {fingerprint:X}");
}
private static void LoadDefaultPublicKey() // fingerprint C3B42B026CE86B21

View file

@ -10,6 +10,17 @@ namespace WTelegram
public static V GetOrCreate<K, V>(this Dictionary<K, V> dictionary, K key) where V : new()
=> dictionary.TryGetValue(key, out V value) ? value : dictionary[key] = new V();
public static Action<int, string> Log { get; set; } = DefaultLogger;
private static readonly ConsoleColor[] LogLevelToColor = new[] { ConsoleColor.DarkGray, ConsoleColor.DarkCyan, ConsoleColor.Cyan,
ConsoleColor.Yellow, ConsoleColor.Red, ConsoleColor.Magenta, ConsoleColor.DarkBlue };
private static void DefaultLogger(int level, string message)
{
Console.ForegroundColor = LogLevelToColor[level];
Console.WriteLine(message);
Console.ResetColor();
}
public static void LittleEndian(byte[] buffer, int offset, int value)
{
buffer[offset + 0] = (byte)value;

View file

@ -31,12 +31,12 @@ namespace WTelegram
var json = File.ReadAllText(pathname);
var session = JsonSerializer.Deserialize<Session>(json, Helpers.JsonOptions);
session._pathname = pathname;
Console.WriteLine("Loaded previous session");
Helpers.Log(2, "Loaded previous session");
return session;
}
catch (Exception ex)
{
Console.WriteLine($"Exception while reading session file: {ex.Message}");
Helpers.Log(4, $"Exception while reading session file: {ex.Message}");
}
}
var sessionId = new byte[8];

19
TL.cs
View file

@ -6,6 +6,7 @@ using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using WTelegram;
namespace TL
{
@ -35,7 +36,7 @@ namespace TL
return memStream.ToArray();
}
internal static T Deserialize<T>(byte[] bytes)
internal static T Deserialize<T>(byte[] bytes) where T : ITLObject
{
using var memStream = new MemoryStream(bytes);
using var reader = new BinaryReader(memStream);
@ -50,7 +51,7 @@ namespace TL
SerializeObject(writer, msg);
}
internal static T Deserialize<T>(BinaryReader reader)
internal static T Deserialize<T>(BinaryReader reader) where T : ITLObject
{
var ctorNb = reader.ReadUInt32();
if (!Mappings.TryGetValue(ctorNb, out var realType))
@ -72,7 +73,7 @@ namespace TL
}
}
internal static object DeserializeObject(BinaryReader reader, Type type)
internal static ITLObject DeserializeObject(BinaryReader reader, Type type)
{
var obj = Activator.CreateInstance(type);
var fields = obj.GetType().GetFields().GroupBy(f => f.DeclaringType).Reverse().SelectMany(g => g);
@ -85,7 +86,7 @@ namespace TL
field.SetValue(obj, value);
if (field.Name.Equals("Flags", StringComparison.OrdinalIgnoreCase)) flags = (int)value;
}
return type == typeof(GzipPacked) ? UnzipPacket((GzipPacked)obj) : obj;
return type == typeof(GzipPacked) ? UnzipPacket((GzipPacked)obj) : (ITLObject)obj;
}
internal static void SerializeValue(BinaryWriter writer, object value)
@ -161,7 +162,7 @@ namespace TL
else if (type.IsValueType)
return DeserializeObject(reader, type);
else
return Deserialize<object>(reader);
return Deserialize<ITLObject>(reader);
default:
ShouldntBeHere();
return null;
@ -239,18 +240,18 @@ namespace TL
}
catch (Exception ex)
{
Console.WriteLine(ex);
Helpers.Log(4, ex.ToString());
}
reader.BaseStream.Position = pos + array[i].bytes;
}
return array;
}
private static object UnzipPacket(GzipPacked obj)
private static ITLObject UnzipPacket(GzipPacked obj)
{
using var reader = new BinaryReader(new GZipStream(new MemoryStream(obj.packed_data), CompressionMode.Decompress));
var result = DeserializeValue(reader, typeof(object));
Console.WriteLine($" → {result.GetType().Name}");
var result = Deserialize<ITLObject>(reader);
Helpers.Log(1, $" → {result.GetType().Name}");
return result;
}

View file

@ -6,6 +6,11 @@
<RootNamespace>WTelegram</RootNamespace>
</PropertyGroup>
<ItemGroup>
<None Remove=".gitattributes" />
<None Remove=".gitignore" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Crc32.NET" Version="1.2.0" />
</ItemGroup>