sochix / TLSharp

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

DC Migration loop #719

Open iz80 opened 6 years ago

iz80 commented 6 years ago

Scenario:

  1. Create a client.
  2. Try to get you contact list with an authenticated account.
  3. Try downloading profile image of another user.
  4. Try accessing your contact list again (just an example).

Between step 0 and 1:

Between step 1 and 2:

On step 3:

Maybe the right solution is to connect to the DC where the file is located without replacing the authentication in the session, but just to use this authentication for the sake of downloading the file. Note that when we get the file object, we already know the DC it's located on.

knocte commented 6 years ago

@iz80 great analysis!

Maybe the right solution is to connect to the DC where the file is located without replacing the authentication in the session, but just to use this authentication for the sake of downloading the file.

Sounds like a sound approach. Do you mind trying to implement it, and if it works for you, propose it as a pull request? Thanks!

iz80 commented 6 years ago

@knocte I would love to, but I'm short on time and afraid that committing to this feature is not something I could do right now. If I could, I would have probably opened this issue with a pull request already.

MahdiHosseiniOfficial commented 6 years ago

@knocte hi , Did you find a solution to this problem?

knocte commented 6 years ago

@MahdiHosseiniOfficial if I had found a solution, I would have already fixed it!

vkomachenok commented 6 years ago

Got the same problem after sequental 10-20 images download. New authorization - and again 10-20 images. Any ideas?

MahdiHosseiniOfficial commented 6 years ago

I'm in the join groups or forward or send message and another method This problem is ready for me But I have an idea . I'm testing it . If the problem is resolved . I'm solve the problem with pull requests

Jarzamendia commented 6 years ago

Any news about that? I'm research a method to avoid too.

guyma-tr commented 6 years ago

Anyone solved it somehow??? After calling GetFile few times the session is corrupted.

vkomachenok commented 6 years ago

As temporarily solution I download html page of message with photo https://t.me/{channelname}/{msgId} and find download links in it.

wetgh12 commented 6 years ago

I have a similar problem. After downloading any image or document, file session.dat gets a new IP address and i have the DataCenterMigrationException and infinit loop. Work under the VPN does not help. Nothing helps.

User located on a different DC: 2. See: https://github.com/sochix/TLSharp#i-get-a-xxxmigrationexception-or-a-migrate_x-error в TLSharp.Core.Network.MtProtoSender.HandleRpcResult(UInt64 messageId, Int32 sequence, BinaryReader messageReader, TLMethod request) в C:\Users\Admln\source\C#\Tlg_Client\TLSharp-master\TLSharp.Core\Network\MtProtoSender.cs:строка 301 в TLSharp.Core.Network.MtProtoSender.processMessage(UInt64 messageId, Int32 sequence, BinaryReader messageReader, TLMethod request) в C:\Users\Admln\source\C#\Tlg_Client\TLSharp-master\TLSharp.Core\Network\MtProtoSender.cs:строка 201 в TLSharp.Core.Network.MtProtoSender.d__8.MoveNext() в C:\Users\Admln\source\C#\Tlg_Client\TLSharp-master\TLSharp.Core\Network\MtProtoSender.cs:строка 139 --- Конец трассировка стека из предыдущего расположения, где возникло исключение --- в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) в System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() в TLSharp.Core.TelegramClient.d__12.MoveNext() в C:\Users\Admln\source\C#\Tlg_Client\TLSharp-master\TLSharp.Core\TelegramClient.cs:строка 122

Only delete session.dat or else i can attach the saved file session.dat, but This also leads to connection problems: "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)". There was only one stupid solution:

    private async Task RequestWithDcMigration(TLMethod request)
    {
        if (_sender == null)
            throw new InvalidOperationException("Not connected!");

        var completed = false;
        while(!completed)
        {
            try
            {
                await _sender.Send(request);
                await _sender.Receive(request);
                completed = true;
            }
            catch(DataCenterMigrationException e)
            {
                C++;
                if (C >= 15) { C = 0; throw new InvalidOperationException("DeadLock in RequestWithDcMigration!"); }
                await ReconnectToDcAsync(e.DC);
                // prepare the request for another try
                request.ConfirmReceived = false;
            }
        }
    }

After that, recovery session.dat from "archive", waiting 15 min and reconnect. Otherwise, it is simply not possible to work.

pesar368 commented 5 years ago

I Have Same Problem . And delete session and re-login does Not Help .

User located on a different DC: 4. See: https://github.com/sochix/TLSharp#i-get-a-xxxmigrationexception-or-a-migrate_x-error

at TLSharp.Core.Network.MtProtoSender.HandleRpcResult(UInt64 messageId, Int32 sequence, BinaryReader messageReader, TLMethod request) in C:\TLSharp.Core\Network\MtProtoSender.cs:line 301 at TLSharp.Core.Network.MtProtoSender.processMessage(UInt64 messageId, Int32 sequence, BinaryReader messageReader, TLMethod request) in C:\TLSharp.Core\Network\MtProtoSender.cs:line 201 at TLSharp.Core.Network.MtProtoSender.d8.MoveNext() in C:\TLSharp.Core\Network\MtProtoSender.cs:line 139 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at TLSharp.Core.TelegramClient.d11.MoveNext() in C:\TLSharp.Core\TelegramClient.cs:line 121

maurodx commented 5 years ago

During DC Migration loop I took a snapshot of my dcOptions inside my client and I saw that I had two different Ipv4 addresses for DC 4 and probably the client tries to switch over the same DC without trying the other ip. Is it something useful?

image

knocte commented 5 years ago

Maybe, based on this info you could modify that behaviour to try to fix the bug?

ilyalatt commented 5 years ago

It is fixed in my library.

ilyalatt commented 5 years ago

The fix is very simple, it can be easily applied to this library as well.

knocte commented 5 years ago

Can you cook a PR based on this please?

zarEclEC commented 5 years ago

Maybe I fixed it

knocte commented 5 years ago

Can someone test his PR please? thanks

zarEclEC commented 5 years ago

It's not an entirely fix, it's just to remove the infinite loop

knocte commented 5 years ago

FYI to everyone watching this bug, a similar approach to @ArmeF97 was committed, so at least now TLSharp will in theory not suffer an infinite loop (but will report a proper exception instead). Try latest master and keep reporting issues related to this until we get to the bottom of it and find a final fix.

AzazelloKAY commented 5 years ago

copy from 839 Have same problem: infinite loop with UserMigrateException after getting image not from my native DC. image receiving; make next req(anything); in RequestWithDcMigration() in "await _sender.Receive(request)" get UserMigrateException then go to "catch" and "await ReconnectToDcAsync(e.DC);" when ReconnectToDcAsync method makes his ExportAuthorization and "exported = await SendRequestAsync<..>(..)" this SendRequestAsync again call RequestWithDcMigration which again gets same exception.... loop

Check "_session.DataCenter.DataCenterId.HasValue" doesn't work because of DataCenter constructor: DataCenter (int? dcId, string address, int port) dcId is null on start.

skipme commented 4 years ago

The library needs to support session for each DC and reuse sessions then migration required. The infinite recursion loop occured then library tries export auth key from current dc to dc which session already established.

knocte commented 4 years ago

@skipme: seems you can reproduce the bug reliably and know how to fix it? I'd pay you some rounds of beers if you could create a PR 🍺

shayattias commented 3 years ago

To those of you who are interested of knowing how to operate this, well in short - that's the flow basically: For every DC that you wish to connect, you should create a new channel and keep the channels separately. The use case as mentioned above: ConnectAsync to the main DC (usually DC with Id 4). Do the authentication with code (or later without). Export the authorization key using the Export method. Then, open a new channel to the different DC. ConnectAsync Import the exported auth key from DC 4 (as stated above) Use the new channel.

Eventually the library should, in my opinion, support management of multiple clients, but that's for a different discussion. Eventually, as far as i understand: Session is meant for: Different users (phones) and different DCs. So phone number XYZ will have multiple session files.

Cheers!