TLSharp/TLSharp.Core/Network/TcpMessage.cs

84 lines
3 KiB
C#
Raw Normal View History

2015-09-28 04:01:17 +02:00
using System;
using System.IO;
using Ionic.Crc;
namespace TLSharp.Core.Network
{
2016-04-18 12:50:57 +02:00
public class TcpMessage
{
public TcpMessage(int seqNumber, byte[] body)
{
if (body == null)
throw new ArgumentNullException(nameof(body));
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
SequneceNumber = seqNumber;
Body = body;
}
2015-09-28 04:01:17 +02:00
2017-04-13 08:38:01 +02:00
public int SequneceNumber { get; }
public byte[] Body { get; }
2016-04-18 12:50:57 +02:00
public byte[] Encode()
{
using (var memoryStream = new MemoryStream())
{
using (var binaryWriter = new BinaryWriter(memoryStream))
{
// https://core.telegram.org/mtproto#tcp-transport
/*
2015-09-28 04:01:17 +02:00
4 length bytes are added at the front
(to include the length, the sequence number, and CRC32; always divisible by 4)
and 4 bytes with the packet sequence number within this TCP connection
(the first packet sent is numbered 0, the next one 1, etc.),
and 4 CRC32 bytes at the end (length, sequence number, and payload together).
*/
2016-04-18 12:50:57 +02:00
binaryWriter.Write(Body.Length + 12);
binaryWriter.Write(SequneceNumber);
binaryWriter.Write(Body);
var crc32 = new CRC32();
crc32.SlurpBlock(memoryStream.GetBuffer(), 0, 8 + Body.Length);
binaryWriter.Write(crc32.Crc32Result);
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
var transportPacket = memoryStream.ToArray();
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
// Debug.WriteLine("Tcp packet #{0}\n{1}", SequneceNumber, BitConverter.ToString(transportPacket));
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
return transportPacket;
}
}
}
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
public static TcpMessage Decode(byte[] body)
{
if (body == null)
throw new ArgumentNullException(nameof(body));
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
if (body.Length < 12)
throw new InvalidOperationException("Ops, wrong size of input packet");
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
using (var memoryStream = new MemoryStream(body))
{
using (var binaryReader = new BinaryReader(memoryStream))
{
var packetLength = binaryReader.ReadInt32();
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
if (packetLength < 12)
throw new InvalidOperationException(string.Format("invalid packet length: {0}", packetLength));
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
var seq = binaryReader.ReadInt32();
2017-04-13 08:38:01 +02:00
var packet = binaryReader.ReadBytes(packetLength - 12);
var checksum = binaryReader.ReadInt32();
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
var crc32 = new CRC32();
crc32.SlurpBlock(body, 0, packetLength - 4);
var validChecksum = crc32.Crc32Result;
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
if (checksum != validChecksum)
throw new InvalidOperationException("invalid checksum! skip");
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
return new TcpMessage(seq, packet);
}
}
}
}
2017-04-13 08:38:01 +02:00
}