Core: refactor around Session vs SessionStore

This will help implementing session storage in JSON
format. WIP PRs:
- https://github.com/nblockchain/TgSharp/pull/18
- https://github.com/nblockchain/TgSharp/pull/29
This commit is contained in:
Andres G. Aragoneses 2020-09-15 00:54:43 +08:00
parent 5ae1024eac
commit ef89274e1f
4 changed files with 52 additions and 57 deletions

View file

@ -2,14 +2,17 @@ namespace TgSharp.Core
{ {
internal class DataCenter internal class DataCenter
{ {
internal DataCenter (int? dcId, string address, int port) private const string defaultConnectionAddress = "149.154.175.100";//"149.154.167.50";
private const int defaultConnectionPort = 443;
internal DataCenter (int? dcId, string address = defaultConnectionAddress, int port = defaultConnectionPort)
{ {
DataCenterId = dcId; DataCenterId = dcId;
Address = address; Address = address;
Port = port; Port = port;
} }
internal DataCenter (string address, int port) : this (null, address, port) internal DataCenter (string address = defaultConnectionAddress, int port = defaultConnectionPort) : this (null, address, port)
{ {
} }

View file

@ -23,13 +23,15 @@ namespace TgSharp.Core.Network
//private ulong sessionId = GenerateRandomUlong(); //private ulong sessionId = GenerateRandomUlong();
private readonly TcpTransport transport; private readonly TcpTransport transport;
private readonly ISessionStore sessionStore;
private readonly Session session; private readonly Session session;
public readonly List<ulong> needConfirmation = new List<ulong>(); public readonly List<ulong> needConfirmation = new List<ulong>();
public MtProtoSender(TcpTransport transport, Session session) public MtProtoSender(TcpTransport transport, ISessionStore sessionStore, Session session)
{ {
this.transport = transport; this.transport = transport;
this.sessionStore = sessionStore;
this.session = session; this.session = session;
} }
@ -63,7 +65,7 @@ namespace TgSharp.Core.Network
await Send(memory.ToArray(), request, token).ConfigureAwait(false); await Send(memory.ToArray(), request, token).ConfigureAwait(false);
} }
session.Save(); sessionStore.Save (session);
} }
public async Task Send(byte[] packet, TLMethod request, CancellationToken token = default(CancellationToken)) public async Task Send(byte[] packet, TLMethod request, CancellationToken token = default(CancellationToken))

View file

@ -71,11 +71,32 @@ namespace TgSharp.Core
} }
} }
internal static class SessionFactory
{
internal static Session TryLoadOrCreateNew (ISessionStore store, string sessionUserId)
{
var session = store.Load (sessionUserId);
if (null == session) {
var defaultDataCenter = new DataCenter ();
session = new Session {
Id = GenerateRandomUlong (),
SessionUserId = sessionUserId,
DataCenter = defaultDataCenter,
};
}
return session;
}
private static ulong GenerateRandomUlong ()
{
var random = new Random ();
ulong rand = (((ulong)random.Next ()) << 32) | ((ulong)random.Next ());
return rand;
}
}
public class Session public class Session
{ {
private const string defaultConnectionAddress = "149.154.175.100";//"149.154.167.50";
private const int defaultConnectionPort = 443;
public int Sequence { get; set; } public int Sequence { get; set; }
#if CI #if CI
// see the same CI-wrapped assignment in .FromBytes(), but this one will become useful // see the same CI-wrapped assignment in .FromBytes(), but this one will become useful
@ -100,12 +121,9 @@ namespace TgSharp.Core
public TLUser TLUser { get; set; } public TLUser TLUser { get; set; }
private Random random; private Random random;
private ISessionStore store; public Session()
public Session(ISessionStore store)
{ {
random = new Random(); random = new Random();
this.store = store;
} }
public byte[] ToBytes() public byte[] ToBytes()
@ -170,7 +188,7 @@ namespace TgSharp.Core
var authData = Serializers.Bytes.Read(reader); var authData = Serializers.Bytes.Read(reader);
var defaultDataCenter = new DataCenter (serverAddress, port); var defaultDataCenter = new DataCenter (serverAddress, port);
return new Session(store) return new Session()
{ {
AuthKey = new AuthKey(authData), AuthKey = new AuthKey(authData),
Id = id, Id = id,
@ -186,30 +204,6 @@ namespace TgSharp.Core
} }
} }
public void Save()
{
store.Save(this);
}
public static Session TryLoadOrCreateNew(ISessionStore store, string sessionUserId)
{
var defaultDataCenter = new DataCenter (defaultConnectionAddress, defaultConnectionPort);
return store.Load(sessionUserId) ?? new Session(store)
{
Id = GenerateRandomUlong(),
SessionUserId = sessionUserId,
DataCenter = defaultDataCenter,
};
}
private static ulong GenerateRandomUlong()
{
var random = new Random();
ulong rand = (((ulong)random.Next()) << 32) | ((ulong)random.Next());
return rand;
}
public long GetNewMessageId() public long GetNewMessageId()
{ {
long time = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds); long time = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds);

View file

@ -31,15 +31,11 @@ namespace TgSharp.Core
private readonly int apiId; private readonly int apiId;
private readonly string sessionUserId; private readonly string sessionUserId;
private readonly ISessionStore store; private readonly ISessionStore store;
private Session session;
private List<TLDcOption> dcOptions; private List<TLDcOption> dcOptions;
private readonly TcpClientConnectionHandler handler; private readonly TcpClientConnectionHandler handler;
private readonly DataCenterIPVersion dcIpVersion; private readonly DataCenterIPVersion dcIpVersion;
public Session Session public Session Session { get; private set; }
{
get { return session; }
}
/// <summary> /// <summary>
/// Creates a new TelegramClient /// Creates a new TelegramClient
@ -83,17 +79,17 @@ namespace TgSharp.Core
{ {
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
session = Session.TryLoadOrCreateNew (store, sessionUserId); Session = SessionFactory.TryLoadOrCreateNew (store, sessionUserId);
transport = new TcpTransport (session.DataCenter.Address, session.DataCenter.Port, this.handler); transport = new TcpTransport (Session.DataCenter.Address, Session.DataCenter.Port, this.handler);
if (session.AuthKey == null || reconnect) if (Session.AuthKey == null || reconnect)
{ {
var result = await Authenticator.DoAuthentication(transport, token).ConfigureAwait(false); var result = await Authenticator.DoAuthentication(transport, token).ConfigureAwait(false);
session.AuthKey = result.AuthKey; Session.AuthKey = result.AuthKey;
session.TimeOffset = result.TimeOffset; Session.TimeOffset = result.TimeOffset;
} }
sender = new MtProtoSender(transport, session); sender = new MtProtoSender(transport, store, Session);
//set-up layer //set-up layer
var config = new TLRequestGetConfig(); var config = new TLRequestGetConfig();
@ -123,7 +119,7 @@ namespace TgSharp.Core
throw new InvalidOperationException($"Can't reconnect. Establish initial connection first."); throw new InvalidOperationException($"Can't reconnect. Establish initial connection first.");
TLExportedAuthorization exported = null; TLExportedAuthorization exported = null;
if (session.TLUser != null) if (Session.TLUser != null)
{ {
TLRequestExportAuthorization exportAuthorization = new TLRequestExportAuthorization() { DcId = dcId }; TLRequestExportAuthorization exportAuthorization = new TLRequestExportAuthorization() { DcId = dcId };
exported = await SendRequestAsync<TLExportedAuthorization>(exportAuthorization, token).ConfigureAwait(false); exported = await SendRequestAsync<TLExportedAuthorization>(exportAuthorization, token).ConfigureAwait(false);
@ -151,12 +147,12 @@ namespace TgSharp.Core
dc = dcs.First(); dc = dcs.First();
var dataCenter = new DataCenter (dcId, dc.IpAddress, dc.Port); var dataCenter = new DataCenter (dcId, dc.IpAddress, dc.Port);
session.DataCenter = dataCenter; Session.DataCenter = dataCenter;
session.Save(); this.store.Save (Session);
await ConnectInternalAsync(true, token).ConfigureAwait(false); await ConnectInternalAsync(true, token).ConfigureAwait(false);
if (session.TLUser != null) if (Session.TLUser != null)
{ {
TLRequestImportAuthorization importAuthorization = new TLRequestImportAuthorization() { Id = exported.Id, Bytes = exported.Bytes }; TLRequestImportAuthorization importAuthorization = new TLRequestImportAuthorization() { Id = exported.Id, Bytes = exported.Bytes };
var imported = await SendRequestAsync<TLAuthorization>(importAuthorization, token).ConfigureAwait(false); var imported = await SendRequestAsync<TLAuthorization>(importAuthorization, token).ConfigureAwait(false);
@ -180,8 +176,8 @@ namespace TgSharp.Core
} }
catch (DataCenterMigrationException e) catch (DataCenterMigrationException e)
{ {
if (session.DataCenter.DataCenterId.HasValue && if (Session.DataCenter.DataCenterId.HasValue &&
session.DataCenter.DataCenterId.Value == e.DC) Session.DataCenter.DataCenterId.Value == e.DC)
{ {
throw new Exception($"Telegram server replied requesting a migration to DataCenter {e.DC} when this connection was already using this DataCenter", e); throw new Exception($"Telegram server replied requesting a migration to DataCenter {e.DC} when this connection was already using this DataCenter", e);
} }
@ -195,7 +191,7 @@ namespace TgSharp.Core
public bool IsUserAuthorized() public bool IsUserAuthorized()
{ {
return session.TLUser != null; return Session.TLUser != null;
} }
public async Task<string> SendCodeRequestAsync(string phoneNumber, CancellationToken token = default(CancellationToken)) public async Task<string> SendCodeRequestAsync(string phoneNumber, CancellationToken token = default(CancellationToken))
@ -427,10 +423,10 @@ namespace TgSharp.Core
private void OnUserAuthenticated(TLUser TLUser) private void OnUserAuthenticated(TLUser TLUser)
{ {
session.TLUser = TLUser; Session.TLUser = TLUser;
session.SessionExpires = int.MaxValue; Session.SessionExpires = int.MaxValue;
session.Save(); this.store.Save (Session);
} }
public bool IsConnected public bool IsConnected