mirror of
https://github.com/wiz0u/WTelegramClient.git
synced 2025-12-06 06:52:01 +01:00
Get rid of ITLFunction lambda writer and use declared ITLMethod<Ret> classes instead
This commit is contained in:
parent
d0be053707
commit
fd9ec2eaed
|
|
@ -44,7 +44,7 @@ namespace WTelegram
|
|||
private static readonly byte[] IntermediateHeader = new byte[4] { 0xee, 0xee, 0xee, 0xee };
|
||||
private TcpClient _tcpClient;
|
||||
private NetworkStream _networkStream;
|
||||
private ITLFunction _lastSentMsg;
|
||||
private ITLObject _lastSentMsg;
|
||||
private long _lastRecvMsgId;
|
||||
private readonly List<long> _msgsToAck = new();
|
||||
private readonly Random _random = new();
|
||||
|
|
@ -143,7 +143,7 @@ namespace WTelegram
|
|||
try
|
||||
{
|
||||
if (CheckMsgsToAck() is MsgsAck msgsAck)
|
||||
SendAsync(MakeFunction(msgsAck), false).Wait(1000);
|
||||
SendAsync(msgsAck, false).Wait(1000);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
|
@ -260,15 +260,18 @@ namespace WTelegram
|
|||
await CreateAuthorizationKey(this, _dcSession);
|
||||
|
||||
var keepAliveTask = KeepAlive(_cts.Token);
|
||||
TLConfig = await this.InvokeWithLayer<Config>(Layer.Version,
|
||||
Schema.InitConnection(_apiId,
|
||||
Config("device_model"),
|
||||
Config("system_version"),
|
||||
Config("app_version"),
|
||||
Config("system_lang_code"),
|
||||
Config("lang_pack"),
|
||||
Config("lang_code"),
|
||||
Schema.Help_GetConfig));
|
||||
TLConfig = await this.InvokeWithLayer(Layer.Version,
|
||||
new Schema.InitConnection_<Config>
|
||||
{
|
||||
api_id = _apiId,
|
||||
device_model = Config("device_model"),
|
||||
system_version = Config("system_version"),
|
||||
app_version = Config("app_version"),
|
||||
system_lang_code = Config("system_lang_code"),
|
||||
lang_pack = Config("lang_pack"),
|
||||
lang_code = Config("lang_code"),
|
||||
query = new Schema.Help_GetConfig_()
|
||||
});
|
||||
_session.DcOptions = TLConfig.dc_options;
|
||||
_saltChangeCounter = 0;
|
||||
if (_dcSession.DataCenter == null)
|
||||
|
|
@ -551,13 +554,13 @@ namespace WTelegram
|
|||
return length;
|
||||
}
|
||||
|
||||
private async Task<long> SendAsync(ITLFunction func, bool isContent)
|
||||
private async Task<long> SendAsync(ITLObject msg, bool isContent)
|
||||
{
|
||||
if (_dcSession.AuthKeyID != 0 && isContent && CheckMsgsToAck() is MsgsAck msgsAck)
|
||||
{
|
||||
var ackMsg = NewMsgId(false);
|
||||
var mainMsg = NewMsgId(true);
|
||||
await SendAsync(MakeContainer((MakeFunction(msgsAck), ackMsg), (func, mainMsg)), false);
|
||||
await SendAsync(MakeContainer((msgsAck, ackMsg), (msg, mainMsg)), false);
|
||||
return mainMsg.msgId;
|
||||
}
|
||||
(long msgId, int seqno) = NewMsgId(isContent && _dcSession.AuthKeyID != 0);
|
||||
|
|
@ -573,8 +576,8 @@ namespace WTelegram
|
|||
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)
|
||||
var typeName = func(writer); // bytes message_data
|
||||
Helpers.Log(1, $"{_dcSession.DcID}>Sending {typeName}...");
|
||||
writer.WriteTLObject(msg); // bytes message_data
|
||||
Helpers.Log(1, $"{_dcSession.DcID}>Sending {msg.GetType().Name}...");
|
||||
BinaryPrimitives.WriteInt32LittleEndian(memStream.GetBuffer().AsSpan(20), (int)memStream.Length - 24); // patch message_data_length
|
||||
}
|
||||
else
|
||||
|
|
@ -592,11 +595,11 @@ namespace WTelegram
|
|||
clearWriter.Write(msgId); // int64 message_id
|
||||
clearWriter.Write(seqno); // int32 msg_seqno
|
||||
clearWriter.Write(0); // int32 message_data_length (to be patched)
|
||||
var typeName = func(clearWriter); // bytes message_data
|
||||
clearWriter.WriteTLObject(msg); // bytes message_data
|
||||
if ((seqno & 1) != 0)
|
||||
Helpers.Log(1, $"{_dcSession.DcID}>Sending {typeName,-40} #{(short)msgId.GetHashCode():X4}");
|
||||
Helpers.Log(1, $"{_dcSession.DcID}>Sending {msg.GetType().Name,-40} #{(short)msgId.GetHashCode():X4}");
|
||||
else
|
||||
Helpers.Log(1, $"{_dcSession.DcID}>Sending {typeName,-40} {MsgIdToStamp(msgId):u} (svc)");
|
||||
Helpers.Log(1, $"{_dcSession.DcID}>Sending {msg.GetType().Name,-40} {MsgIdToStamp(msgId):u} (svc)");
|
||||
int clearLength = (int)clearStream.Length - prepend; // length before padding (= 32 + message_data_length)
|
||||
int padding = (0x7FFFFFF0 - clearLength) % 16;
|
||||
#if !MTPROTO1
|
||||
|
|
@ -626,7 +629,7 @@ namespace WTelegram
|
|||
//TODO: support Transport obfuscation?
|
||||
|
||||
await _networkStream.WriteAsync(memStream.GetBuffer(), 0, frameLength);
|
||||
_lastSentMsg = func;
|
||||
_lastSentMsg = msg;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -635,13 +638,6 @@ namespace WTelegram
|
|||
return msgId;
|
||||
}
|
||||
|
||||
private static ITLFunction MakeFunction(ITLObject msg)
|
||||
=> writer =>
|
||||
{
|
||||
writer.WriteTLObject(msg);
|
||||
return msg.GetType().Name;
|
||||
};
|
||||
|
||||
internal MsgContainer ReadMsgContainer(TL.BinaryReader reader)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
|
|
@ -727,7 +723,7 @@ namespace WTelegram
|
|||
return request;
|
||||
}
|
||||
|
||||
internal async Task<X> CallBareAsync<X>(ITLFunction request)
|
||||
internal async Task<X> CallBareAsync<X>(ITLMethod<X> request)
|
||||
{
|
||||
if (_bareRequest != 0) throw new ApplicationException("A bare request is already undergoing");
|
||||
var msgId = await SendAsync(request, false);
|
||||
|
|
@ -740,9 +736,9 @@ namespace WTelegram
|
|||
|
||||
/// <summary>Call the given TL method <i>(You shouldn't need to call this, usually)</i></summary>
|
||||
/// <typeparam name="X">Expected type of the returned object</typeparam>
|
||||
/// <param name="request">TL method serializer</param>
|
||||
/// <param name="request">TL method object</param>
|
||||
/// <returns>Wait for the reply and return the resulting object, or throws an RpcException if an error was replied</returns>
|
||||
public async Task<X> CallAsync<X>(ITLFunction request)
|
||||
public async Task<X> CallAsync<X>(ITLMethod<X> request)
|
||||
{
|
||||
retry:
|
||||
var msgId = await SendAsync(request, true);
|
||||
|
|
@ -806,27 +802,15 @@ namespace WTelegram
|
|||
}
|
||||
}
|
||||
|
||||
private ITLFunction MakeContainer(params (ITLFunction func, (long msgId, int seqno))[] msgs)
|
||||
=> writer =>
|
||||
private static MsgContainer MakeContainer(params (ITLObject obj, (long msgId, int seqno))[] msgs)
|
||||
=> new()
|
||||
{
|
||||
writer.Write(0x73F1F8DC);
|
||||
writer.Write(msgs.Length);
|
||||
foreach (var (func, (msgId, seqno)) in msgs)
|
||||
messages = msgs.Select(msg => new _Message
|
||||
{
|
||||
writer.Write(msgId);
|
||||
writer.Write(seqno);
|
||||
var patchPos = writer.BaseStream.Position;
|
||||
writer.Write(0);
|
||||
var typeName = func(writer);
|
||||
if ((seqno & 1) != 0)
|
||||
Helpers.Log(1, $" Sending → {typeName,-40} #{(short)msgId.GetHashCode():X4}");
|
||||
else
|
||||
Helpers.Log(1, $" Sending → {typeName,-40} {MsgIdToStamp(msgId):u} (svc)");
|
||||
writer.BaseStream.Position = patchPos;
|
||||
writer.Write((int)(writer.BaseStream.Length - patchPos - 4)); // patch bytes field
|
||||
writer.Seek(0, SeekOrigin.End);
|
||||
}
|
||||
return "as MsgContainer";
|
||||
msg_id = msg.Item2.msgId,
|
||||
seqno = msg.Item2.seqno,
|
||||
body = msg.obj
|
||||
}).ToArray()
|
||||
};
|
||||
|
||||
private async Task HandleMessageAsync(ITLObject obj)
|
||||
|
|
@ -855,8 +839,8 @@ namespace WTelegram
|
|||
}
|
||||
}
|
||||
break;
|
||||
case Ping ping:
|
||||
_ = SendAsync(MakeFunction(new Pong { msg_id = _lastRecvMsgId, ping_id = ping.ping_id }), false);
|
||||
case MTProto.Ping_ ping:
|
||||
_ = SendAsync(new Pong { msg_id = _lastRecvMsgId, ping_id = ping.ping_id }, false);
|
||||
break;
|
||||
case Pong pong:
|
||||
SetResult(pong.msg_id, pong);
|
||||
|
|
|
|||
|
|
@ -293,111 +293,130 @@ namespace TL
|
|||
public AccessPointRule[] rules;
|
||||
}
|
||||
|
||||
[TLDef(0x7ABE77EC)] //ping#7abe77ec ping_id:long = Pong
|
||||
public partial class Ping : ITLObject
|
||||
{
|
||||
public long ping_id;
|
||||
}
|
||||
|
||||
// ---functions---
|
||||
|
||||
public static class MTProto
|
||||
{
|
||||
//req_pq#60469778 nonce:int128 = ResPQ
|
||||
[TLDef(0x60469778)] //req_pq#60469778 nonce:int128 = ResPQ
|
||||
public partial class ReqPq_ : ITLMethod<ResPQ>
|
||||
{
|
||||
public Int128 nonce;
|
||||
}
|
||||
public static Task<ResPQ> ReqPq(this Client client, Int128 nonce)
|
||||
=> client.CallBareAsync<ResPQ>(writer =>
|
||||
=> client.CallBareAsync(new ReqPq_
|
||||
{
|
||||
writer.Write(0x60469778);
|
||||
writer.Write(nonce);
|
||||
return "ReqPq";
|
||||
nonce = nonce,
|
||||
});
|
||||
|
||||
//req_pq_multi#be7e8ef1 nonce:int128 = ResPQ
|
||||
[TLDef(0xBE7E8EF1)] //req_pq_multi#be7e8ef1 nonce:int128 = ResPQ
|
||||
public partial class ReqPqMulti_ : ITLMethod<ResPQ>
|
||||
{
|
||||
public Int128 nonce;
|
||||
}
|
||||
public static Task<ResPQ> ReqPqMulti(this Client client, Int128 nonce)
|
||||
=> client.CallBareAsync<ResPQ>(writer =>
|
||||
=> client.CallBareAsync(new ReqPqMulti_
|
||||
{
|
||||
writer.Write(0xBE7E8EF1);
|
||||
writer.Write(nonce);
|
||||
return "ReqPqMulti";
|
||||
nonce = nonce,
|
||||
});
|
||||
|
||||
//req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:bytes q:bytes public_key_fingerprint:long encrypted_data:bytes = Server_DH_Params
|
||||
[TLDef(0xD712E4BE)] //req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:bytes q:bytes public_key_fingerprint:long encrypted_data:bytes = Server_DH_Params
|
||||
public partial class ReqDHParams_ : ITLMethod<ServerDHParams>
|
||||
{
|
||||
public Int128 nonce;
|
||||
public Int128 server_nonce;
|
||||
public byte[] p;
|
||||
public byte[] q;
|
||||
public long public_key_fingerprint;
|
||||
public byte[] encrypted_data;
|
||||
}
|
||||
public static Task<ServerDHParams> ReqDHParams(this Client client, Int128 nonce, Int128 server_nonce, byte[] p, byte[] q, long public_key_fingerprint, byte[] encrypted_data)
|
||||
=> client.CallBareAsync<ServerDHParams>(writer =>
|
||||
=> client.CallBareAsync(new ReqDHParams_
|
||||
{
|
||||
writer.Write(0xD712E4BE);
|
||||
writer.Write(nonce);
|
||||
writer.Write(server_nonce);
|
||||
writer.WriteTLBytes(p);
|
||||
writer.WriteTLBytes(q);
|
||||
writer.Write(public_key_fingerprint);
|
||||
writer.WriteTLBytes(encrypted_data);
|
||||
return "ReqDHParams";
|
||||
nonce = nonce,
|
||||
server_nonce = server_nonce,
|
||||
p = p,
|
||||
q = q,
|
||||
public_key_fingerprint = public_key_fingerprint,
|
||||
encrypted_data = encrypted_data,
|
||||
});
|
||||
|
||||
//set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:bytes = Set_client_DH_params_answer
|
||||
[TLDef(0xF5045F1F)] //set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:bytes = Set_client_DH_params_answer
|
||||
public partial class SetClientDHParams_ : ITLMethod<SetClientDHParamsAnswer>
|
||||
{
|
||||
public Int128 nonce;
|
||||
public Int128 server_nonce;
|
||||
public byte[] encrypted_data;
|
||||
}
|
||||
public static Task<SetClientDHParamsAnswer> SetClientDHParams(this Client client, Int128 nonce, Int128 server_nonce, byte[] encrypted_data)
|
||||
=> client.CallBareAsync<SetClientDHParamsAnswer>(writer =>
|
||||
=> client.CallBareAsync(new SetClientDHParams_
|
||||
{
|
||||
writer.Write(0xF5045F1F);
|
||||
writer.Write(nonce);
|
||||
writer.Write(server_nonce);
|
||||
writer.WriteTLBytes(encrypted_data);
|
||||
return "SetClientDHParams";
|
||||
nonce = nonce,
|
||||
server_nonce = server_nonce,
|
||||
encrypted_data = encrypted_data,
|
||||
});
|
||||
|
||||
//destroy_auth_key#d1435160 = DestroyAuthKeyRes
|
||||
[TLDef(0xD1435160)] //destroy_auth_key#d1435160 = DestroyAuthKeyRes
|
||||
public partial class DestroyAuthKey_ : ITLMethod<DestroyAuthKeyRes> { }
|
||||
public static Task<DestroyAuthKeyRes> DestroyAuthKey(this Client client)
|
||||
=> client.CallBareAsync<DestroyAuthKeyRes>(writer =>
|
||||
=> client.CallBareAsync(new DestroyAuthKey_
|
||||
{
|
||||
writer.Write(0xD1435160);
|
||||
return "DestroyAuthKey";
|
||||
});
|
||||
|
||||
//rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer
|
||||
[TLDef(0x58E4A740)] //rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer
|
||||
public partial class RpcDropAnswer_ : ITLMethod<RpcDropAnswer>
|
||||
{
|
||||
public long req_msg_id;
|
||||
}
|
||||
public static Task<RpcDropAnswer> RpcDropAnswer(this Client client, long req_msg_id)
|
||||
=> client.CallBareAsync<RpcDropAnswer>(writer =>
|
||||
=> client.CallBareAsync(new RpcDropAnswer_
|
||||
{
|
||||
writer.Write(0x58E4A740);
|
||||
writer.Write(req_msg_id);
|
||||
return "RpcDropAnswer";
|
||||
req_msg_id = req_msg_id,
|
||||
});
|
||||
|
||||
//get_future_salts#b921bd04 num:int = FutureSalts
|
||||
[TLDef(0xB921BD04)] //get_future_salts#b921bd04 num:int = FutureSalts
|
||||
public partial class GetFutureSalts_ : ITLMethod<FutureSalts>
|
||||
{
|
||||
public int num;
|
||||
}
|
||||
public static Task<FutureSalts> GetFutureSalts(this Client client, int num)
|
||||
=> client.CallAsync<FutureSalts>(writer =>
|
||||
=> client.CallAsync(new GetFutureSalts_
|
||||
{
|
||||
writer.Write(0xB921BD04);
|
||||
writer.Write(num);
|
||||
return "GetFutureSalts";
|
||||
num = num,
|
||||
});
|
||||
|
||||
//ping#7abe77ec ping_id:long = Pong
|
||||
[TLDef(0x7ABE77EC)] //ping#7abe77ec ping_id:long = Pong
|
||||
public partial class Ping_ : ITLMethod<Pong>
|
||||
{
|
||||
public long ping_id;
|
||||
}
|
||||
public static Task<Pong> Ping(this Client client, long ping_id)
|
||||
=> client.CallAsync<Pong>(writer =>
|
||||
=> client.CallAsync(new Ping_
|
||||
{
|
||||
writer.Write(0x7ABE77EC);
|
||||
writer.Write(ping_id);
|
||||
return "Ping";
|
||||
ping_id = ping_id,
|
||||
});
|
||||
|
||||
//ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong
|
||||
[TLDef(0xF3427B8C)] //ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong
|
||||
public partial class PingDelayDisconnect_ : ITLMethod<Pong>
|
||||
{
|
||||
public long ping_id;
|
||||
public int disconnect_delay;
|
||||
}
|
||||
public static Task<Pong> PingDelayDisconnect(this Client client, long ping_id, int disconnect_delay)
|
||||
=> client.CallAsync<Pong>(writer =>
|
||||
=> client.CallAsync(new PingDelayDisconnect_
|
||||
{
|
||||
writer.Write(0xF3427B8C);
|
||||
writer.Write(ping_id);
|
||||
writer.Write(disconnect_delay);
|
||||
return "PingDelayDisconnect";
|
||||
ping_id = ping_id,
|
||||
disconnect_delay = disconnect_delay,
|
||||
});
|
||||
|
||||
//destroy_session#e7512126 session_id:long = DestroySessionRes
|
||||
[TLDef(0xE7512126)] //destroy_session#e7512126 session_id:long = DestroySessionRes
|
||||
public partial class DestroySession_ : ITLMethod<DestroySessionRes>
|
||||
{
|
||||
public long session_id;
|
||||
}
|
||||
public static Task<DestroySessionRes> DestroySession(this Client client, long session_id)
|
||||
=> client.CallBareAsync<DestroySessionRes>(writer =>
|
||||
=> client.CallBareAsync(new DestroySession_
|
||||
{
|
||||
writer.Write(0xE7512126);
|
||||
writer.Write(session_id);
|
||||
return "DestroySession";
|
||||
session_id = session_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
8125
src/TL.Schema.cs
8125
src/TL.Schema.cs
File diff suppressed because it is too large
Load diff
|
|
@ -34,7 +34,7 @@ namespace TL
|
|||
[0x3BCBF734] = typeof(DhGenOk),
|
||||
[0x46DC1FB9] = typeof(DhGenRetry),
|
||||
[0xA69DAE02] = typeof(DhGenFail),
|
||||
[0x7ABE77EC] = typeof(Ping),
|
||||
[0x7ABE77EC] = typeof(MTProto.Ping_),
|
||||
[0x62D6B459] = typeof(MsgsAck),
|
||||
[0xA7EFF811] = typeof(BadMsgNotification),
|
||||
[0xEDAB447B] = typeof(BadServerSalt),
|
||||
|
|
|
|||
24
src/TL.cs
24
src/TL.cs
|
|
@ -10,7 +10,7 @@ using System.Text;
|
|||
namespace TL
|
||||
{
|
||||
public interface ITLObject { }
|
||||
public delegate string ITLFunction(BinaryWriter writer);
|
||||
public interface ITLMethod<ReturnType> : ITLObject { }
|
||||
|
||||
public static class Serialization
|
||||
{
|
||||
|
|
@ -94,6 +94,8 @@ namespace TL
|
|||
if (type.IsArray)
|
||||
if (value is byte[] bytes)
|
||||
writer.WriteTLBytes(bytes);
|
||||
else if (value is _Message[] messages)
|
||||
writer.WriteTLMessages(messages);
|
||||
else
|
||||
writer.WriteTLVector((Array)value);
|
||||
else if (value is Int128 int128)
|
||||
|
|
@ -164,6 +166,26 @@ namespace TL
|
|||
writer.WriteTLValue(array.GetValue(i), elementType);
|
||||
}
|
||||
|
||||
internal static void WriteTLMessages(this BinaryWriter writer, _Message[] messages)
|
||||
{
|
||||
writer.Write(messages.Length);
|
||||
foreach (var msg in messages)
|
||||
{
|
||||
writer.Write(msg.msg_id);
|
||||
writer.Write(msg.seqno);
|
||||
var patchPos = writer.BaseStream.Position;
|
||||
writer.Write(0); // patched below
|
||||
writer.WriteTLObject(msg.body);
|
||||
if ((msg.seqno & 1) != 0)
|
||||
WTelegram.Helpers.Log(1, $" Sending → {msg.body.GetType().Name,-40} #{(short)msg.msg_id.GetHashCode():X4}");
|
||||
else
|
||||
WTelegram.Helpers.Log(1, $" Sending → {msg.body.GetType().Name,-40}");
|
||||
writer.BaseStream.Position = patchPos;
|
||||
writer.Write((int)(writer.BaseStream.Length - patchPos - 4)); // patch bytes field
|
||||
writer.Seek(0, SeekOrigin.End);
|
||||
}
|
||||
}
|
||||
|
||||
internal static Array ReadTLVector(this BinaryReader reader, Type type)
|
||||
{
|
||||
var elementType = type.GetElementType();
|
||||
|
|
|
|||
Loading…
Reference in a new issue