From c67801a6c9750c905b0c5bdf449780cfc1fb3809 Mon Sep 17 00:00:00 2001 From: solarin Date: Sun, 5 Apr 2020 19:22:36 +0400 Subject: [PATCH] Added an IPv4/IPv6 toggle to TelegramClient constructor (#925) Fixes https://github.com/sochix/TLSharp/issues/857 --- TLSharp.Core/DataCenterIPVersion.cs | 30 ++++++++++++++++++++++++ TLSharp.Core/Network/TcpTransport.cs | 8 ++++++- TLSharp.Core/TLSharp.Core.csproj | 1 + TLSharp.Core/TelegramClient.cs | 34 ++++++++++++++++++++++++++-- 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 TLSharp.Core/DataCenterIPVersion.cs diff --git a/TLSharp.Core/DataCenterIPVersion.cs b/TLSharp.Core/DataCenterIPVersion.cs new file mode 100644 index 0000000..7b8b825 --- /dev/null +++ b/TLSharp.Core/DataCenterIPVersion.cs @@ -0,0 +1,30 @@ +namespace TLSharp.Core +{ + /// + /// When the Telegram server responds with a set of addresses to connect to, DataCenterIPVersion indicates a preference + /// for how to choose the IP address to connect to + /// + public enum DataCenterIPVersion + { + /// + /// Picks the first available address passed by Telegram + /// + Default, + /// + /// Takes only IPv4 addresses + /// + OnlyIPv4, + /// + /// Takes only IPv6 addresses + /// + OnlyIPv6, + /// + /// Connection to IPv4 addresses is preferred to IPv6 addresses + /// + PreferIPv4, + /// + /// Connection to IPv6 addresses is preferred to IPv4 addresses + /// + PreferIPv6, + } +} diff --git a/TLSharp.Core/Network/TcpTransport.cs b/TLSharp.Core/Network/TcpTransport.cs index d60d881..cfc7956 100644 --- a/TLSharp.Core/Network/TcpTransport.cs +++ b/TLSharp.Core/Network/TcpTransport.cs @@ -24,7 +24,13 @@ namespace TLSharp.Core.Network var endpoint = new IPEndPoint(ipAddress, port); tcpClient = new TcpClient(ipAddress.AddressFamily); - tcpClient.Connect(endpoint); + + try { + tcpClient.Connect (endpoint); + } catch (Exception ex) { + throw new Exception ($"Problem when trying to connect to {endpoint}; either there's no internet connection or the IP address version is not compatible (if the latter, consider using DataCenterIPVersion enum)", + ex); + } } else tcpClient = handler(address, port); diff --git a/TLSharp.Core/TLSharp.Core.csproj b/TLSharp.Core/TLSharp.Core.csproj index 4dff090..9924ab2 100644 --- a/TLSharp.Core/TLSharp.Core.csproj +++ b/TLSharp.Core/TLSharp.Core.csproj @@ -45,6 +45,7 @@ + diff --git a/TLSharp.Core/TelegramClient.cs b/TLSharp.Core/TelegramClient.cs index 46e0ad4..765ecbf 100644 --- a/TLSharp.Core/TelegramClient.cs +++ b/TLSharp.Core/TelegramClient.cs @@ -31,14 +31,25 @@ namespace TLSharp.Core private Session session; private List dcOptions; private TcpClientConnectionHandler handler; + private DataCenterIPVersion dcIpVersion; public Session Session { get { return session; } } + /// + /// Creates a new TelegramClient + /// + /// The API ID provided by Telegram. Get one at https://my.telegram.org + /// The API Hash provided by Telegram. Get one at https://my.telegram.org + /// An ISessionStore object that will handle the session + /// The name of the session that tracks login info about this TelegramClient connection + /// A delegate to invoke when a connection is needed and that will return a TcpClient that will be used to connect + /// Indicates the preferred IpAddress version to use to connect to a Telegram server public TelegramClient(int apiId, string apiHash, - ISessionStore store = null, string sessionUserId = "session", TcpClientConnectionHandler handler = null) + ISessionStore store = null, string sessionUserId = "session", TcpClientConnectionHandler handler = null, + DataCenterIPVersion dcIpVersion = DataCenterIPVersion.Default) { if (apiId == default(int)) throw new MissingApiConfigurationException("API_ID"); @@ -51,6 +62,7 @@ namespace TLSharp.Core this.apiHash = apiHash; this.apiId = apiId; this.handler = handler; + this.dcIpVersion = dcIpVersion; session = Session.TryLoadOrCreateNew(store, sessionUserId); transport = new TcpTransport (session.DataCenter.Address, session.DataCenter.Port, this.handler); @@ -101,7 +113,25 @@ namespace TLSharp.Core exported = await SendRequestAsync(exportAuthorization, token).ConfigureAwait(false); } - var dc = dcOptions.First(d => d.Id == dcId); + IEnumerable dcs; + if (dcIpVersion == DataCenterIPVersion.OnlyIPv6) + dcs = dcOptions.Where(d => d.Id == dcId && d.Ipv6); // selects only ipv6 addresses + else if (dcIpVersion == DataCenterIPVersion.OnlyIPv4) + dcs = dcOptions.Where(d => d.Id == dcId && !d.Ipv6); // selects only ipv4 addresses + else + dcs = dcOptions.Where(d => d.Id == dcId); // any + + TLDcOption dc; + if (dcIpVersion != DataCenterIPVersion.Default) + { + if (!dcs.Any()) + throw new Exception($"Telegram server didn't provide us with any IPAddress that matches your preferences. If you chose OnlyIPvX, try switch to PreferIPvX instead."); + dcs = dcs.OrderBy(d => d.Ipv6); + dc = dcIpVersion == DataCenterIPVersion.PreferIPv4 ? dcs.First() : dcs.Last(); // ipv4 addresses are at the beginning of the list because it was ordered + } + else + dc = dcs.First(); + var dataCenter = new DataCenter (dcId, dc.IpAddress, dc.Port); transport = new TcpTransport(dc.IpAddress, dc.Port, handler);