Skip to content
This repository was archived by the owner on Dec 5, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion TLSharp.Core/Auth/Step3_CompleteDHExchange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -206,4 +206,11 @@ public Step3_Response FromBytes(byte[] response)
}
}
}
internal class InvalidNewNonceHashException : Exception
{
internal InvalidNewNonceHashException() : base("invalid new nonce hash")
{

}
}
}
48 changes: 45 additions & 3 deletions TLSharp.Core/Network/MtProtoSender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ private Tuple<byte[], ulong, int> 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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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; }
Expand Down Expand Up @@ -571,4 +613,4 @@ internal UserMigrationException(int dc)
{
}
}
}
}
202 changes: 108 additions & 94 deletions TLSharp.Core/Network/TcpTransport.cs
Original file line number Diff line number Diff line change
@@ -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<TcpMessage> 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<TcpMessage> 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")
{

}
}
}