mirror of
https://github.com/wiz0u/WTelegramClient.git
synced 2025-12-06 06:52:01 +01:00
Process Downloads really on media DCs, including for the main dc_id (fix #261)
This commit is contained in:
parent
f7b3a56ce3
commit
9712233c00
|
|
@ -314,7 +314,7 @@ namespace WTelegram
|
||||||
public async Task<Storage_FileType> DownloadFileAsync(InputFileLocationBase fileLocation, Stream outputStream, int dc_id = 0, long fileSize = 0, ProgressCallback progress = null)
|
public async Task<Storage_FileType> DownloadFileAsync(InputFileLocationBase fileLocation, Stream outputStream, int dc_id = 0, long fileSize = 0, ProgressCallback progress = null)
|
||||||
{
|
{
|
||||||
Storage_FileType fileType = Storage_FileType.unknown;
|
Storage_FileType fileType = Storage_FileType.unknown;
|
||||||
var client = dc_id == 0 ? this : await GetClientForDC(dc_id, true);
|
var client = dc_id == 0 ? this : await GetClientForDC(-dc_id, true);
|
||||||
using var writeSem = new SemaphoreSlim(1);
|
using var writeSem = new SemaphoreSlim(1);
|
||||||
bool canSeek = outputStream.CanSeek;
|
bool canSeek = outputStream.CanSeek;
|
||||||
long streamStartPos = canSeek ? outputStream.Position : 0;
|
long streamStartPos = canSeek ? outputStream.Position : 0;
|
||||||
|
|
@ -347,7 +347,7 @@ namespace WTelegram
|
||||||
}
|
}
|
||||||
catch (RpcException ex) when (ex.Code == 303 && ex.Message == "FILE_MIGRATE_X")
|
catch (RpcException ex) when (ex.Code == 303 && ex.Message == "FILE_MIGRATE_X")
|
||||||
{
|
{
|
||||||
client = await GetClientForDC(ex.X, true);
|
client = await GetClientForDC(-ex.X, true);
|
||||||
fileBase = await client.Upload_GetFile(fileLocation, offset, FilePartSize);
|
fileBase = await client.Upload_GetFile(fileLocation, offset, FilePartSize);
|
||||||
}
|
}
|
||||||
catch (RpcException ex) when (ex.Code == 400 && ex.Message == "OFFSET_INVALID")
|
catch (RpcException ex) when (ex.Code == 400 && ex.Message == "OFFSET_INVALID")
|
||||||
|
|
|
||||||
|
|
@ -240,13 +240,24 @@ namespace WTelegram
|
||||||
|
|
||||||
private Session.DCSession GetOrCreateDCSession(int dcId, DcOption.Flags flags)
|
private Session.DCSession GetOrCreateDCSession(int dcId, DcOption.Flags flags)
|
||||||
{
|
{
|
||||||
if (_session.DCSessions.TryGetValue(dcId, out var dcSession))
|
if (_session.DCSessions.TryGetValue(dcId, out var dcSession) && dcSession.AuthKey != null)
|
||||||
if (dcSession.Client != null || dcSession.DataCenter.flags == flags)
|
if (dcSession.Client != null || dcSession.DataCenter.flags == flags)
|
||||||
return dcSession; // if we have already a session with this DC and we are connected or it is a perfect match, use it
|
return dcSession; // if we have already a session with this DC and we are connected or it is a perfect match, use it
|
||||||
|
if (dcSession == null && _session.DCSessions.TryGetValue(-dcId, out dcSession) && dcSession.AuthKey != null)
|
||||||
|
{
|
||||||
|
if (dcSession.DataCenter.flags == flags && _session.DCSessions.Remove(-dcId))
|
||||||
|
return _session.DCSessions[dcId] = dcSession; // we found a misclassed DC, change its sign
|
||||||
|
dcSession = new Session.DCSession { Id = Helpers.RandomLong(), // clone AuthKey for a session on the matching media_only DC
|
||||||
|
AuthKeyID = dcSession.AuthKeyID, AuthKey = dcSession.AuthKey, UserId = dcSession.UserId };
|
||||||
|
}
|
||||||
// try to find the most appropriate DcOption for this DC
|
// try to find the most appropriate DcOption for this DC
|
||||||
if ((dcSession?.AuthKeyID ?? 0) == 0) // we will need to negociate an AuthKey => can't use media_only DC
|
if (dcSession?.AuthKey == null) // we'll need to negociate an AuthKey => can't use media_only DC
|
||||||
|
{
|
||||||
flags &= ~DcOption.Flags.media_only;
|
flags &= ~DcOption.Flags.media_only;
|
||||||
var dcOptions = _session.DcOptions.Where(dc => dc.id == dcId).OrderBy(dc => dc.flags ^ flags);
|
dcId = Math.Abs(dcId);
|
||||||
|
}
|
||||||
|
var dcOptions = _session.DcOptions.Where(dc => dc.id == Math.Abs(dcId))
|
||||||
|
.OrderBy(dc => dc.flags.HasFlag(DcOption.Flags.media_only) ^ (dcId < 0)).ThenBy(dc => dc.flags ^ flags);
|
||||||
var dcOption = dcOptions.FirstOrDefault() ?? throw new WTException($"Could not find adequate dc_option for DC {dcId}");
|
var dcOption = dcOptions.FirstOrDefault() ?? throw new WTException($"Could not find adequate dc_option for DC {dcId}");
|
||||||
dcSession ??= new Session.DCSession { Id = Helpers.RandomLong() }; // create new session only if not already existing
|
dcSession ??= new Session.DCSession { Id = Helpers.RandomLong() }; // create new session only if not already existing
|
||||||
dcSession.DataCenter = dcOption;
|
dcSession.DataCenter = dcOption;
|
||||||
|
|
@ -254,17 +265,18 @@ namespace WTelegram
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Obtain/create a Client for a secondary session on a specific Data Center</summary>
|
/// <summary>Obtain/create a Client for a secondary session on a specific Data Center</summary>
|
||||||
/// <param name="dcId">ID of the Data Center</param>
|
/// <param name="dcId">ID of the Data Center (use negative values for media_only)</param>
|
||||||
/// <param name="media_only">Session will be used only for transferring media</param>
|
|
||||||
/// <param name="connect">Connect immediately</param>
|
/// <param name="connect">Connect immediately</param>
|
||||||
/// <returns>Client connected to the selected DC</returns>
|
/// <returns>Client connected to the selected DC</returns>
|
||||||
public async Task<Client> GetClientForDC(int dcId, bool media_only = true, bool connect = true)
|
public async Task<Client> GetClientForDC(int dcId, bool connect = true)
|
||||||
{
|
{
|
||||||
if (_dcSession.DataCenter?.id == dcId) return this;
|
if (_dcSession.DataCenter?.id == dcId) return this;
|
||||||
Session.DCSession altSession;
|
Session.DCSession altSession;
|
||||||
lock (_session)
|
lock (_session)
|
||||||
{
|
{
|
||||||
altSession = GetOrCreateDCSession(dcId, _dcSession.DataCenter.flags | (media_only ? DcOption.Flags.media_only : 0));
|
var flags = _dcSession.DataCenter.flags;
|
||||||
|
if (dcId < 0) flags = (flags & DcOption.Flags.ipv6) | DcOption.Flags.media_only;
|
||||||
|
altSession = GetOrCreateDCSession(dcId, flags);
|
||||||
if (altSession.Client?.Disconnected ?? false) { altSession.Client.Dispose(); altSession.Client = null; }
|
if (altSession.Client?.Disconnected ?? false) { altSession.Client.Dispose(); altSession.Client = null; }
|
||||||
altSession.Client ??= new Client(this, altSession);
|
altSession.Client ??= new Client(this, altSession);
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +288,7 @@ namespace WTelegram
|
||||||
{
|
{
|
||||||
Auth_ExportedAuthorization exported = null;
|
Auth_ExportedAuthorization exported = null;
|
||||||
if (_session.UserId != 0 && IsMainDC && altSession.UserId != _session.UserId)
|
if (_session.UserId != 0 && IsMainDC && altSession.UserId != _session.UserId)
|
||||||
exported = await this.Auth_ExportAuthorization(dcId);
|
exported = await this.Auth_ExportAuthorization(Math.Abs(dcId));
|
||||||
await altSession.Client.ConnectAsync();
|
await altSession.Client.ConnectAsync();
|
||||||
if (exported != null)
|
if (exported != null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue