TLSharp/TLSharp.Core/Network/MtProtoPlainSender.cs
CheshireCaat c5a2c816fc Improvements for async methods
Added CancellationToken with default value to all async methods in TLSharp.Core
Added ConfigureAwait(false) to all async methods in TLSharp.Core
SendRequestAsync replaced to SendAuthenticatedRequestAsync in methods that need auth
Private modifier in SendAuthenticatedRequestAsync changed to internal

Based on PR created by @IaRuslan
2020-01-28 10:10:49 +03:00

82 lines
2.7 KiB
C#

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace TLSharp.Core.Network
{
public class MtProtoPlainSender
{
private int timeOffset;
private long lastMessageId;
private Random random;
private TcpTransport _transport;
public MtProtoPlainSender(TcpTransport transport)
{
_transport = transport;
random = new Random();
}
public async Task Send(byte[] data, CancellationToken token = default(CancellationToken))
{
token.ThrowIfCancellationRequested();
using (var memoryStream = new MemoryStream())
{
using (var binaryWriter = new BinaryWriter(memoryStream))
{
binaryWriter.Write((long)0);
binaryWriter.Write(GetNewMessageId());
binaryWriter.Write(data.Length);
binaryWriter.Write(data);
byte[] packet = memoryStream.ToArray();
await _transport.Send(packet, token).ConfigureAwait(false);
}
}
}
public async Task<byte[]> Receive(CancellationToken token = default(CancellationToken))
{
token.ThrowIfCancellationRequested();
var result = await _transport.Receive(token).ConfigureAwait(false);
using (var memoryStream = new MemoryStream(result.Body))
{
using (BinaryReader binaryReader = new BinaryReader(memoryStream))
{
long authKeyid = binaryReader.ReadInt64();
long messageId = binaryReader.ReadInt64();
int messageLength = binaryReader.ReadInt32();
byte[] response = binaryReader.ReadBytes(messageLength);
return response;
}
}
}
private long GetNewMessageId()
{
long time = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds);
long newMessageId = ((time / 1000 + timeOffset) << 32) |
((time % 1000) << 22) |
(random.Next(524288) << 2); // 2^19
// [ unix timestamp : 32 bit] [ milliseconds : 10 bit ] [ buffer space : 1 bit ] [ random : 19 bit ] [ msg_id type : 2 bit ] = [ msg_id : 64 bit ]
if (lastMessageId >= newMessageId)
{
newMessageId = lastMessageId + 4;
}
lastMessageId = newMessageId;
return newMessageId;
}
}
}