sochix / TLSharp

Telegram client library implemented in C#
1.01k stars 380 forks source link

I get Only IPv6 address from DC #857

Closed IvnSrv closed 4 years ago

IvnSrv commented 5 years ago

I have a problem with this, well, I can't receive IPv4 address, and my ISP doesn't support IPv6 addreses. How can I do?

I dump the dcOptions. image

I'm using .Net Core 2.2.300.

In Network.TcpTransport, I change this: _tcpClient = new TcpClient(endpoint); (Because I couldn't connect with any address, even default IPv4) to this:

_tcpClient = new TcpClient(address, port);
if (!_tcpClient.Connected) _tcpClient.Connect(endpoint);

And connect OK with default IPv4 address, but when I ask for code (SendCodeRequestAsync), it change DataCenter and I only gave IPv6 addresses :(... (Yes, I changed this dcOptions.FirstOrDefault(d => d.Id == dcId && !d.Ipv6);)...

How can I only receive IPv4 addresses?

Thanks!

knocte commented 5 years ago

@CloneDeath ping? ^

IvnSrv commented 5 years ago

Well, I changed the default IP. I used the IP test that my.telegram.org gave me, and I awaited about 2 hours and then, it connected!...

But, now I can't receive confirmation code: image I don't know why port 80 is used in IPv4.

And yes, I verified that the number were ok, starting with "+"...

About ping, well my ISP doesn't support IPv6 connection, so, I can't ping to any public IPv6 addresses.

IvnSrv commented 5 years ago

¡It's alive! Well, I use Production IP and not the Test IP and everything OK, I made some changes to connection class (nothing especial)... Thanks!

You can close this thread.

knocte commented 5 years ago

I made some changes to connection class (nothing especial)...

What are these changes?

CloneDeath commented 5 years ago

@IvnSrv if you just push to your fork, and link to the branch, I can take a look and see if I can incorporate those changes.

@knocte We may have to incorporate some option to filter out IPv6 addresses... I don't like the option idea, because... people just wouldn't know! Plus, it might work on my dev env, but not on your prod env... Ideally, I'd like to detect this... unfortunately, Socket.OSSupportsIPv6 (something like that) only checks your OS, not your chain through your router/modem, so if your modem doesn't support it, then Socket.OSSupportsIPv6 will still return true if you're on like Win10...

I'd be interested to see what IvnSrv did to get it working... I imagine just disabling IPv6 altogether.

IvnSrv commented 5 years ago

Well... I did all this:

1) I change the TelegramClientconstructor: image So, I can change manually the default IP that the project has (Optionally if you can see).

2) I modified TryLoadOrCreateNew method: image Nothing special if you can see, but, now I can change what IP want when I'm creating a new Telegram Client. Obviously, you can add a validator, maybe, instead of string, you could use IPAddress.

3) I change the TcpTransport (THIS WAS VERY IMPORTANT TO ME) to this:

public TcpTransport(string address, int port, TcpClientConnectionHandler handler = null)
    {
      if (handler == null)
      {
        var ipAddress = IPAddress.Parse(address);
        var endpoint = new IPEndPoint(ipAddress, port);

        try
        {
          Console.WriteLine($"Testing connection by EndPoint: {address}:{port}");
          _tcpClient = new TcpClient(endpoint); //THIS LINE GAVE ME ERROR ALWAYS (even when I deactivate IPv6 support from my network config)
          _tcpClient.Connect(endpoint);
        }
        catch (Exception e)
        {
          //CONSOLE FOR TESTING PURPOSES
          Console.WriteLine("------------CONEXIÓN TCP------------");
          Console.WriteLine("Endpoint failed!");
          Console.WriteLine(e.Message);
          Console.WriteLine(e.StackTrace);
          Console.WriteLine("------------------------------------");
          Console.WriteLine($"Alternative connection ({address}, {port})...");

        _tcpClient = new TcpClient(address, port); //HERE CONNECTION OK
          if (!_tcpClient.Connected) _tcpClient.Connect(endpoint);
          Console.WriteLine("¡CONECTADO!"+Environment.NewLine);
        }
      }
      else
        _tcpClient = handler(address, port);
    }

Explanation: Well, in session class, you're using another IP (149.154.175.100), but, I don't know why, always gave me IPv6 addresses, well, I change this IP from the IP that my.telegram.org gave me (For production, test IP fail too). And obviously in method: ReconnectToDcAsync I change the code to: var dc = dcOptions.FirstOrDefault(d => d.Id == dcId && !d.Ipv6); This line gave me error because I don't receive any IPv4 address xD...

And that's it!

You can add an option like: "ForceIPv4only" and if is true, modify the dc Linq query. I don't know, is only an idea, for now, as in my country IPv6 isn't supported, I have to force IPv4 manually...

CloneDeath commented 5 years ago

I'm not on your machine, so I can only speculate, but I think your first two changes aren't important, JUST the IPv4 change is relevant (since, when it gets to there, I bet it would work with IPv4 address for you, just as it does for me)

I'm going to make an IPv4OnlyTelegramClient class that inherits from TelegramClient, that, obviously only uses IPv4 datacenters. There will be a little bit of refactoring, ofc.

CloneDeath commented 5 years ago

I ended up just making it an optional constructor param.

CloneDeath commented 5 years ago

@IvnSrv So, the IPv4 only fix wouldn't work for you, since you were not getting any IPv4 addresses... how did you get around that? We're you just ignoring the migration request, and just using the same datacenter?

knocte commented 5 years ago

@IvnSrv did you get an exception when connecting to IPv6 addresses? If yes, please copy+paste the entire exception here (ex.ToString()).

IvnSrv commented 5 years ago

@IvnSrv So, the IPv4 only fix wouldn't work for you, since you were not getting any IPv4 addresses... how did you get around that? We're you just ignoring the migration request, and just using the same datacenter?

Well, I change the default IP from 149.154.175.100 to 149.154.167.50, and, I don't know why, but it works... Sometimes, first IP gave me IPv4 addresses, but not always.

@IvnSrv did you get an exception when connecting to IPv6 addresses? If yes, please copy+paste the entire exception here (ex.ToString()).

Ok, this is the ex.ToString():

System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (10051): Se ha intentado una operación de socket en una red no accesible [2001:b28:f23d:f001::e]:443
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at System.Net.Sockets.Socket.Connect(IPAddress address, Int32 port)
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
   at System.Net.Sockets.TcpClient..ctor(String hostname, Int32 port)
   at TLSharp.Core.Network.TcpTransport..ctor(String address, Int32 port, TcpClientConnectionHandler handler)
   at TLSharp.Core.TelegramClient.ReconnectToDcAsync(Int32 dcId)
   at TLSharp.Core.TelegramClient.RequestWithDcMigration(TLMethod request)
   at TLSharp.Core.TelegramClient.SendCodeRequestAsync(String phoneNumber)
   at TlgramSRV.Telegram.Cliente.NuevoCliente(Int32 ApiID, String ApiHash, String teléfono) in D:\NET Core Projects\TlgramSRV\Telegram\Cliente.cs:line 29
   at TlgramSRV.Program.Conectar() in D:\NET Core Projects\TlgramSRV\Program.cs:line 25

Well, I have VS in spanish, sorry, but this is the translation: "A socket operation was attempted to an unreachable network [2001:b28:f23d:f001::e]:443"

But, when I try to ping an IPv6 address, well: image

If you can see, I can't ping it, even when IPv6 protocol are active, but, that's an ISP problem :(, I think that in several countries, well, they doesn't has this problem.

knocte commented 5 years ago

@CloneDeath how about catching the above exception (10051 means "NetworkUnreachable" according to https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socketerror), and, in case IPv6 was being used, try IPv4 instead (if it fails with IPv4 too, re-throw).