diff --git a/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs b/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs index 8ba8f5a3..fb23613a 100644 --- a/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs +++ b/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs @@ -175,7 +175,7 @@ public Step3_Response FromBytes(byte[] response) if (!newNonceHash1.SequenceEqual(newNonceHashCalculated)) { - throw new InvalidOperationException("invalid new nonce hash"); + throw new InvalidNewNonceHashException(); } //logger.info("generated new auth key: {0}", gab); @@ -206,4 +206,11 @@ public Step3_Response FromBytes(byte[] response) } } } + internal class InvalidNewNonceHashException : Exception + { + internal InvalidNewNonceHashException() : base("invalid new nonce hash") + { + + } + } } diff --git a/TLSharp.Core/Network/MtProtoSender.cs b/TLSharp.Core/Network/MtProtoSender.cs index 8a959caa..4f34af15 100644 --- a/TLSharp.Core/Network/MtProtoSender.cs +++ b/TLSharp.Core/Network/MtProtoSender.cs @@ -110,7 +110,7 @@ private Tuple DecodeMessage(byte[] body) using (var inputReader = new BinaryReader(inputStream)) { if (inputReader.BaseStream.Length < 8) - throw new InvalidOperationException($"Can't decode packet"); + throw new DecodePacketException(); ulong remoteAuthKeyId = inputReader.ReadUInt64(); // TODO: check auth key id byte[] msgKey = inputReader.ReadBytes(16); // TODO: check msg_key correctness @@ -313,6 +313,15 @@ private bool HandleRpcResult(ulong messageId, int sequence, BinaryReader message { throw new CloudPasswordNeededException("This Account has Cloud Password !"); } + else if (errorMessage == "AUTH_KEY_UNREGISTERED") + { + // + throw new AuthKeyUnregisteredException(); + } + else if (errorMessage == "RPC_MCGET_FAIL") + { + throw new RpcMcGetFailException(); + } else { throw new InvalidOperationException(errorMessage); @@ -378,7 +387,7 @@ private bool HandleBadMsgNotification(ulong messageId, int sequence, BinaryReade case 20: throw new InvalidOperationException("message too old, and it cannot be verified whether the server has received a message with this msg_id or not"); case 32: - throw new InvalidOperationException("msg_seqno too low (the server has already received a message with a lower msg_id but with either a higher or an equal and odd seqno)"); + throw new MsgSeqnoTooLowException(); case 33: throw new InvalidOperationException(" msg_seqno too high (similarly, there is a message with a higher msg_id but with either a lower or an equal and odd seqno)"); case 34: @@ -535,6 +544,39 @@ internal FloodException(TimeSpan timeToWait) } } + internal class DecodePacketException : Exception + { + internal DecodePacketException() : base("Can't decode packet.") + { + + } + } + public class AuthKeyUnregisteredException : Exception + { + internal AuthKeyUnregisteredException() : base("Auth key is unregistered.") + { + + } + } + + internal class RpcMcGetFailException : Exception + { + internal RpcMcGetFailException() : base("Rpc Mc Get Fail.") + { + + } + } + + internal class MsgSeqnoTooLowException : Exception + { + internal MsgSeqnoTooLowException() : base("msg_seqno too low (the server has already received a message with a lower msg_id but with either a higher or an equal and odd seqno)") + { + + } + } + + + internal abstract class DataCenterMigrationException : Exception { internal int DC { get; private set; } @@ -571,4 +613,4 @@ internal UserMigrationException(int dc) { } } -} \ No newline at end of file +} diff --git a/TLSharp.Core/Network/TcpTransport.cs b/TLSharp.Core/Network/TcpTransport.cs index 254153ed..6d0d74a7 100644 --- a/TLSharp.Core/Network/TcpTransport.cs +++ b/TLSharp.Core/Network/TcpTransport.cs @@ -1,95 +1,109 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading.Tasks; - -namespace TLSharp.Core.Network -{ - public delegate TcpClient TcpClientConnectionHandler(string address, int port); - - public class TcpTransport : IDisposable - { - private readonly TcpClient _tcpClient; - private int sendCounter = 0; - - public TcpTransport(string address, int port, TcpClientConnectionHandler handler = null) - { - if (handler == null) - { - _tcpClient = new TcpClient(); - - var ipAddress = IPAddress.Parse(address); - _tcpClient.Connect(ipAddress, port); - } - else - _tcpClient = handler(address, port); - } - - public async Task Send(byte[] packet) - { - if (!_tcpClient.Connected) - throw new InvalidOperationException("Client not connected to server."); - - var tcpMessage = new TcpMessage(sendCounter, packet); - - await _tcpClient.GetStream().WriteAsync(tcpMessage.Encode(), 0, tcpMessage.Encode().Length); - sendCounter++; - } - - public async Task Receieve() - { - var stream = _tcpClient.GetStream(); - - var packetLengthBytes = new byte[4]; - if (await stream.ReadAsync(packetLengthBytes, 0, 4) != 4) - throw new InvalidOperationException("Couldn't read the packet length"); - int packetLength = BitConverter.ToInt32(packetLengthBytes, 0); - - var seqBytes = new byte[4]; - if (await stream.ReadAsync(seqBytes, 0, 4) != 4) - throw new InvalidOperationException("Couldn't read the sequence"); - int seq = BitConverter.ToInt32(seqBytes, 0); - - int readBytes = 0; - var body = new byte[packetLength - 12]; - int neededToRead = packetLength - 12; - - do - { - var bodyByte = new byte[packetLength - 12]; - var availableBytes = await stream.ReadAsync(bodyByte, 0, neededToRead); - neededToRead -= availableBytes; - Buffer.BlockCopy(bodyByte, 0, body, readBytes, availableBytes); - readBytes += availableBytes; - } - while (readBytes != packetLength - 12); - - var crcBytes = new byte[4]; - if (await stream.ReadAsync(crcBytes, 0, 4) != 4) - throw new InvalidOperationException("Couldn't read the crc"); - int checksum = BitConverter.ToInt32(crcBytes, 0); - - byte[] rv = new byte[packetLengthBytes.Length + seqBytes.Length + body.Length]; - - Buffer.BlockCopy(packetLengthBytes, 0, rv, 0, packetLengthBytes.Length); - Buffer.BlockCopy(seqBytes, 0, rv, packetLengthBytes.Length, seqBytes.Length); - Buffer.BlockCopy(body, 0, rv, packetLengthBytes.Length + seqBytes.Length, body.Length); - var crc32 = new Ionic.Crc.CRC32(); - crc32.SlurpBlock(rv, 0, rv.Length); - var validChecksum = crc32.Crc32Result; - - if (checksum != validChecksum) - { - throw new InvalidOperationException("invalid checksum! skip"); - } - - return new TcpMessage(seq, body); - } - - public void Dispose() - { - if (_tcpClient.Connected) - _tcpClient.Close(); +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading.Tasks; + +namespace TLSharp.Core.Network +{ + public delegate TcpClient TcpClientConnectionHandler(string address, int port); + + public class TcpTransport : IDisposable + { + private readonly TcpClient _tcpClient; + private int sendCounter = 0; + + public TcpTransport(string address, int port, TcpClientConnectionHandler handler = null) + { + if (handler == null) + { + _tcpClient = new TcpClient(); + + var ipAddress = IPAddress.Parse(address); + _tcpClient.Connect(ipAddress, port); + } + else + _tcpClient = handler(address, port); } - } -} + + public async Task Send(byte[] packet) + { + if (!_tcpClient.Connected) + throw new TcpClientNotConnectedException(); + + var tcpMessage = new TcpMessage(sendCounter, packet); + + await _tcpClient.GetStream().WriteAsync(tcpMessage.Encode(), 0, tcpMessage.Encode().Length); + sendCounter++; + } + + public async Task Receieve() + { + var stream = _tcpClient.GetStream(); + + var packetLengthBytes = new byte[4]; + if (await stream.ReadAsync(packetLengthBytes, 0, 4) != 4) + throw new TcpClientCouldntReadPacketLengthException(); + int packetLength = BitConverter.ToInt32(packetLengthBytes, 0); + + var seqBytes = new byte[4]; + if (await stream.ReadAsync(seqBytes, 0, 4) != 4) + throw new InvalidOperationException("Couldn't read the sequence"); + int seq = BitConverter.ToInt32(seqBytes, 0); + + int readBytes = 0; + var body = new byte[packetLength - 12]; + int neededToRead = packetLength - 12; + + do + { + var bodyByte = new byte[packetLength - 12]; + var availableBytes = await stream.ReadAsync(bodyByte, 0, neededToRead); + neededToRead -= availableBytes; + Buffer.BlockCopy(bodyByte, 0, body, readBytes, availableBytes); + readBytes += availableBytes; + } + while (readBytes != packetLength - 12); + + var crcBytes = new byte[4]; + if (await stream.ReadAsync(crcBytes, 0, 4) != 4) + throw new InvalidOperationException("Couldn't read the crc"); + int checksum = BitConverter.ToInt32(crcBytes, 0); + + byte[] rv = new byte[packetLengthBytes.Length + seqBytes.Length + body.Length]; + + Buffer.BlockCopy(packetLengthBytes, 0, rv, 0, packetLengthBytes.Length); + Buffer.BlockCopy(seqBytes, 0, rv, packetLengthBytes.Length, seqBytes.Length); + Buffer.BlockCopy(body, 0, rv, packetLengthBytes.Length + seqBytes.Length, body.Length); + var crc32 = new Ionic.Crc.CRC32(); + crc32.SlurpBlock(rv, 0, rv.Length); + var validChecksum = crc32.Crc32Result; + + if (checksum != validChecksum) + { + throw new InvalidOperationException("invalid checksum! skip"); + } + + return new TcpMessage(seq, body); + } + + public void Dispose() + { + if (_tcpClient.Connected) + _tcpClient.Close(); + } + } + internal class TcpClientNotConnectedException : Exception + { + internal TcpClientNotConnectedException() : base("Client not connected to server.") + { + + } + } + internal class TcpClientCouldntReadPacketLengthException : Exception + { + internal TcpClientCouldntReadPacketLengthException() : base("Couldn't read the packet length") + { + + } + } +}