Gracefully handle a disconnection from an idle secondary DC

(don't reconnect)
This commit is contained in:
Wizou 2021-11-21 00:43:39 +01:00
parent e8a98a5799
commit 934895a81c
4 changed files with 20 additions and 18 deletions

9
FAQ.md
View file

@ -1,6 +1,6 @@
## FAQ
#### 1. How to remove the Console logs ?
#### 1. How to remove the Console logs?
Writing the library logs to the Console is the default behavior of the `WTelegram.Helpers.Log` delegate.
You can change the delegate with the `+=` operator to **also** write them somewhere else, or with the `=` operator to prevent them from being printed to screen and instead write them somewhere (file, logger, ...).
@ -14,7 +14,7 @@ The WTelegram.session file contains the authentication keys negociated for the c
You could switch the current user via an `Auth_Logout` followed by a `LoginUserIfNeeded` but that would require the user to sign in with a verification_code each time.
Instead, if you want to deal with multiple users, the recommended solution is to have a different session file for each user. This can be done by having your Config callback reply with a different filename (or folder) for "**session_pathname**" for each user.
Instead, if you want to deal with multiple users from the same machine, the recommended solution is to have a different session file for each user. This can be done by having your Config callback reply with a different filename (or folder) for "**session_pathname**" for each user.
This way, you can keep separate session files (each with their authentication keys) for each user.
If you need to manage these user accounts in parallel, you can create multiple instances of WTelegram.Client, and give them a Config callback that will select a different session file.
@ -97,14 +97,13 @@ Here are some key points:
*(the above section is derived from [gotd SUPPORT.md](https://github.com/gotd/td/blob/main/.github/SUPPORT.md))*
#### 8. I can't import phone numbers. I get error PHONE_NUMBER_BANNED or FLOOD_WAIT_84200
#### 8. I can't import phone numbers. I get error PHONE_NUMBER_BANNED or FLOOD_WAIT_8xxxx
You can get these kind of problems if you abuse Telegram [Terms of Service](https://telegram.org/tos) or make excessive requests.
You can try to wait more between the requests, wait for a day or two to see if the requests become possible again.
If you think your phone number was banned for a bad reason, you may try to contact [recover@telegram.org](mailto:recover@telegram.org), explaining what you were doing.
If you think your phone number was banned for a wrong reason, you may try to contact [recover@telegram.org](mailto:recover@telegram.org), explaining what you were doing.
In any case, WTelegramClient is not responsible for the bad usage of the library and we are not affiliated to Telegram teams, so there is nothing we can do.

View file

@ -61,7 +61,7 @@ There are other configuration items that are queried to your method but returnin
Those shown above are the only ones that have no default values and <u>should be provided</u> by your method.
Returning `null` for verification_code or password will show a prompt for console apps, or an error otherwise.
Another simpler approach is to pass `Environment.GetEnvironmentVariable` as the config callback and define the configuration items as environment variables.
Another simple approach is to pass `Environment.GetEnvironmentVariable` as the config callback and define the configuration items as environment variables.
Undefined variables get the default `null` behavior.
Finally, if you want to redirect the library logs to your logger instead of the Console, you can install a delegate in the `WTelegram.Helpers.Log` static property.
@ -101,7 +101,7 @@ Console.WriteLine($"Sending a message in chat {chatId}: {target.Title}");
await client.SendMessageAsync(target, "Hello, World");
```
You can find more useful code snippets in [EXAMPLES.md](https://github.com/wiz0u/WTelegramClient/blob/master/EXAMPLES.md) and in the [Examples subdirectory](https://github.com/wiz0u/WTelegramClient/tree/master/Examples).
➡️ You can find more useful code snippets in [EXAMPLES.md](https://github.com/wiz0u/WTelegramClient/blob/master/EXAMPLES.md) and in the [Examples subdirectory](https://github.com/wiz0u/WTelegramClient/tree/master/Examples).
# Terminology in Telegram Client API
@ -142,6 +142,6 @@ Secret chats (end-to-end encryption, PFS) and connection to CDN DCs have not bee
Please don't use this library for Spam or Scam. Respect Telegram [Terms of Service](https://telegram.org/tos) or you might get banned from Telegram servers.
Developers feedbacks are welcome in the Telegram support group [@WTelegramClient](https://t.me/WTelegramClient)
You can also check our [Frequently Asked Questions](https://github.com/wiz0u/WTelegramClient/blob/master/FAQ.md) for more help and troubleshooting guide.
You can also check our [📖 Frequently Asked Questions](https://github.com/wiz0u/WTelegramClient/blob/master/FAQ.md) for more help and troubleshooting guide.
If you like this library, please [consider a donation](http://wizou.fr/donate.html). ❤ This will help the project keep going.
If you like this library, please [consider a donation](http://wizou.fr/donate.html).❤ This will help the project keep going.

View file

@ -63,6 +63,7 @@ namespace WTelegram
private CancellationTokenSource _cts;
private int _reactorReconnects = 0;
private const int FilePartSize = 512 * 1024;
private const string ConnectionShutDown = "Could not read payload length : Connection shut down";
private readonly SemaphoreSlim _parallelTransfers = new(10); // max parallel part uploads/downloads
#if MTPROTO1
private readonly SHA1 _sha1 = SHA1.Create();
@ -391,7 +392,7 @@ namespace WTelegram
try
{
if (await FullReadAsync(stream, data, 4, cts.Token) != 4)
throw new ApplicationException("Could not read payload length : Connection shut down");
throw new ApplicationException(ConnectionShutDown);
int payloadLen = BinaryPrimitives.ReadInt32LittleEndian(data);
if (payloadLen > data.Length)
data = new byte[payloadLen];
@ -405,17 +406,20 @@ namespace WTelegram
catch (Exception ex) // an exception in RecvAsync is always fatal
{
if (cts.IsCancellationRequested) return;
Helpers.Log(5, $"An exception occured in the reactor: {ex}");
Helpers.Log(5, $"{_dcSession.DcID}>An exception occured in the reactor: {ex}");
var oldSemaphore = _sendSemaphore;
await oldSemaphore.WaitAsync(cts.Token); // prevent any sending while we reconnect
var reactorError = new ReactorError { Exception = ex };
try
{
lock (_msgsToAck) _msgsToAck.Clear();
Reset(false, false);
_reactorReconnects = (_reactorReconnects + 1) % MaxAutoReconnects;
if (!IsMainDC && _pendingRequests.Count <= 1 && ex is ApplicationException { Message: ConnectionShutDown } or IOException { InnerException: SocketException })
if (_pendingRequests.Values.FirstOrDefault() is var (type, tcs) && (type is null || type == typeof(Pong)))
_reactorReconnects = 0;
if (_reactorReconnects != 0)
{
lock (_msgsToAck) _msgsToAck.Clear();
Reset(false, false);
await Task.Delay(5000);
await ConnectAsync(); // start a new reactor after 5 secs
lock (_pendingRequests) // retry all pending requests
@ -450,7 +454,6 @@ namespace WTelegram
{
oldSemaphore.Release();
}
cts.Cancel(); // always stop the reactor
}
if (obj != null)
await HandleMessageAsync(obj);
@ -584,8 +587,8 @@ namespace WTelegram
writer.Write(0L); // int64 auth_key_id = 0 (Unencrypted)
writer.Write(msgId); // int64 message_id
writer.Write(0); // int32 message_data_length (to be patched)
writer.WriteTLObject(msg); // bytes message_data
Helpers.Log(1, $"{_dcSession.DcID}>Sending {msg.GetType().Name.TrimEnd('_')}...");
writer.WriteTLObject(msg); // bytes message_data
BinaryPrimitives.WriteInt32LittleEndian(memStream.GetBuffer().AsSpan(20), (int)memStream.Length - 24); // patch message_data_length
}
else
@ -603,11 +606,11 @@ namespace WTelegram
clearWriter.Write(msgId); // int64 message_id
clearWriter.Write(seqno); // int32 msg_seqno
clearWriter.Write(0); // int32 message_data_length (to be patched)
clearWriter.WriteTLObject(msg); // bytes message_data
if ((seqno & 1) != 0)
Helpers.Log(1, $"{_dcSession.DcID}>Sending {msg.GetType().Name.TrimEnd('_'),-40} #{(short)msgId.GetHashCode():X4}");
else
Helpers.Log(1, $"{_dcSession.DcID}>Sending {msg.GetType().Name.TrimEnd('_'),-40} {MsgIdToStamp(msgId):u} (svc)");
clearWriter.WriteTLObject(msg); // bytes message_data
int clearLength = (int)clearStream.Length - prepend; // length before padding (= 32 + message_data_length)
int padding = (0x7FFFFFF0 - clearLength) % 16;
#if !MTPROTO1

View file

@ -178,9 +178,9 @@ namespace TL
writer.Write(0); // patched below
writer.WriteTLObject(msg.body);
if ((msg.seqno & 1) != 0)
WTelegram.Helpers.Log(1, $" Sending → {msg.body.GetType().Name.TrimEnd('_'),-40} #{(short)msg.msg_id.GetHashCode():X4}");
WTelegram.Helpers.Log(1, $" → {msg.body.GetType().Name.TrimEnd('_'),-38} #{(short)msg.msg_id.GetHashCode():X4}");
else
WTelegram.Helpers.Log(1, $" Sending → {msg.body.GetType().Name.TrimEnd('_'),-40}");
WTelegram.Helpers.Log(1, $" → {msg.body.GetType().Name.TrimEnd('_'),-38}");
writer.BaseStream.Position = patchPos;
writer.Write((int)(writer.BaseStream.Length - patchPos - 4)); // patch bytes field
writer.Seek(0, SeekOrigin.End);