Added an IPv4/IPv6 toggle to TelegramClient constructor (#925)

Fixes https://github.com/sochix/TLSharp/issues/857
This commit is contained in:
solarin 2020-04-05 19:22:36 +04:00 committed by GitHub
parent 6d2c77f5ef
commit c67801a6c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 3 deletions

View file

@ -0,0 +1,30 @@
namespace TLSharp.Core
{
/// <summary>
/// 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
/// </summary>
public enum DataCenterIPVersion
{
/// <summary>
/// Picks the first available address passed by Telegram
/// </summary>
Default,
/// <summary>
/// Takes only IPv4 addresses
/// </summary>
OnlyIPv4,
/// <summary>
/// Takes only IPv6 addresses
/// </summary>
OnlyIPv6,
/// <summary>
/// Connection to IPv4 addresses is preferred to IPv6 addresses
/// </summary>
PreferIPv4,
/// <summary>
/// Connection to IPv6 addresses is preferred to IPv4 addresses
/// </summary>
PreferIPv6,
}
}

View file

@ -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);

View file

@ -45,6 +45,7 @@
<Compile Include="Auth\Step1_PQRequest.cs" />
<Compile Include="Auth\Step2_DHExchange.cs" />
<Compile Include="Auth\Step3_CompleteDHExchange.cs" />
<Compile Include="DataCenterIPVersion.cs" />
<Compile Include="Exceptions\CloudPasswordNeededException.cs" />
<Compile Include="Exceptions\InvalidPhoneCodeException.cs" />
<Compile Include="Exceptions\MissingApiConfigurationException.cs" />

View file

@ -31,14 +31,25 @@ namespace TLSharp.Core
private Session session;
private List<TLDcOption> dcOptions;
private TcpClientConnectionHandler handler;
private DataCenterIPVersion dcIpVersion;
public Session Session
{
get { return session; }
}
/// <summary>
/// Creates a new TelegramClient
/// </summary>
/// <param name="apiId">The API ID provided by Telegram. Get one at https://my.telegram.org </param>
/// <param name="apiHash">The API Hash provided by Telegram. Get one at https://my.telegram.org </param>
/// <param name="store">An ISessionStore object that will handle the session</param>
/// <param name="sessionUserId">The name of the session that tracks login info about this TelegramClient connection</param>
/// <param name="handler">A delegate to invoke when a connection is needed and that will return a TcpClient that will be used to connect</param>
/// <param name="dcIpVersion">Indicates the preferred IpAddress version to use to connect to a Telegram server</param>
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<TLExportedAuthorization>(exportAuthorization, token).ConfigureAwait(false);
}
var dc = dcOptions.First(d => d.Id == dcId);
IEnumerable<TLDcOption> 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);