2020-04-02 10:37:22 +02:00
|
|
|
using System;
|
2015-09-28 04:01:17 +02:00
|
|
|
using System.IO;
|
2016-09-22 15:31:59 +02:00
|
|
|
using TeleSharp.TL;
|
2020-04-02 10:37:22 +02:00
|
|
|
using TgSharp.Core.MTProto;
|
|
|
|
|
using TgSharp.Core.MTProto.Crypto;
|
2015-09-28 04:01:17 +02:00
|
|
|
|
2020-04-02 10:37:22 +02:00
|
|
|
namespace TgSharp.Core
|
2015-09-28 04:01:17 +02:00
|
|
|
{
|
2016-04-18 12:50:57 +02:00
|
|
|
public interface ISessionStore
|
|
|
|
|
{
|
|
|
|
|
void Save(Session session);
|
|
|
|
|
Session Load(string sessionUserId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class FileSessionStore : ISessionStore
|
|
|
|
|
{
|
2019-10-05 06:39:41 +02:00
|
|
|
private readonly DirectoryInfo basePath;
|
|
|
|
|
|
|
|
|
|
public FileSessionStore(DirectoryInfo basePath = null)
|
|
|
|
|
{
|
|
|
|
|
if (basePath != null && !basePath.Exists)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException("basePath doesn't exist", nameof(basePath));
|
|
|
|
|
}
|
|
|
|
|
this.basePath = basePath;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-18 12:50:57 +02:00
|
|
|
public void Save(Session session)
|
|
|
|
|
{
|
2019-10-05 06:39:41 +02:00
|
|
|
string sessionFileName = $"{session.SessionUserId}.dat";
|
|
|
|
|
var sessionPath = basePath == null ? sessionFileName :
|
|
|
|
|
Path.Combine(basePath.FullName, sessionFileName);
|
|
|
|
|
|
|
|
|
|
using (var stream = new FileStream(sessionPath, FileMode.OpenOrCreate))
|
2016-04-18 12:50:57 +02:00
|
|
|
{
|
|
|
|
|
var result = session.ToBytes();
|
|
|
|
|
stream.Write(result, 0, result.Length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Session Load(string sessionUserId)
|
|
|
|
|
{
|
2019-10-05 06:39:41 +02:00
|
|
|
string sessionFileName = $"{sessionUserId}.dat";
|
|
|
|
|
var sessionPath = basePath == null ? sessionFileName :
|
|
|
|
|
Path.Combine(basePath.FullName, sessionFileName);
|
|
|
|
|
|
|
|
|
|
if (!File.Exists(sessionPath))
|
2016-09-06 17:20:06 +02:00
|
|
|
return null;
|
|
|
|
|
|
2019-10-05 06:39:41 +02:00
|
|
|
using (var stream = new FileStream(sessionPath, FileMode.Open))
|
2016-04-18 12:50:57 +02:00
|
|
|
{
|
|
|
|
|
var buffer = new byte[2048];
|
|
|
|
|
stream.Read(buffer, 0, 2048);
|
|
|
|
|
|
|
|
|
|
return Session.FromBytes(buffer, this, sessionUserId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class FakeSessionStore : ISessionStore
|
|
|
|
|
{
|
|
|
|
|
public void Save(Session session)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Session Load(string sessionUserId)
|
|
|
|
|
{
|
2016-09-06 17:20:06 +02:00
|
|
|
return null;
|
2016-04-18 12:50:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class Session
|
|
|
|
|
{
|
2016-10-15 12:35:54 +02:00
|
|
|
private const string defaultConnectionAddress = "149.154.175.100";//"149.154.167.50";
|
|
|
|
|
|
|
|
|
|
private const int defaultConnectionPort = 443;
|
2016-04-18 12:50:57 +02:00
|
|
|
|
|
|
|
|
public string SessionUserId { get; set; }
|
2019-02-10 13:53:46 +01:00
|
|
|
internal DataCenter DataCenter { get; set; }
|
2016-04-18 12:50:57 +02:00
|
|
|
public AuthKey AuthKey { get; set; }
|
|
|
|
|
public ulong Id { get; set; }
|
|
|
|
|
public int Sequence { get; set; }
|
|
|
|
|
public ulong Salt { get; set; }
|
|
|
|
|
public int TimeOffset { get; set; }
|
|
|
|
|
public long LastMessageId { get; set; }
|
|
|
|
|
public int SessionExpires { get; set; }
|
2016-09-24 15:38:26 +02:00
|
|
|
public TLUser TLUser { get; set; }
|
2016-04-18 12:50:57 +02:00
|
|
|
private Random random;
|
|
|
|
|
|
2020-01-31 07:39:19 +01:00
|
|
|
private ISessionStore store;
|
2016-04-18 12:50:57 +02:00
|
|
|
|
2017-12-16 19:15:16 +01:00
|
|
|
public Session(ISessionStore store)
|
2016-04-18 12:50:57 +02:00
|
|
|
{
|
|
|
|
|
random = new Random();
|
2020-01-31 07:39:19 +01:00
|
|
|
this.store = store;
|
2016-04-18 12:50:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public byte[] ToBytes()
|
|
|
|
|
{
|
|
|
|
|
using (var stream = new MemoryStream())
|
|
|
|
|
using (var writer = new BinaryWriter(stream))
|
|
|
|
|
{
|
|
|
|
|
writer.Write(Id);
|
|
|
|
|
writer.Write(Sequence);
|
|
|
|
|
writer.Write(Salt);
|
|
|
|
|
writer.Write(LastMessageId);
|
|
|
|
|
writer.Write(TimeOffset);
|
2020-01-25 07:40:24 +01:00
|
|
|
Serializers.String.Write(writer, DataCenter.Address);
|
2019-02-10 13:53:46 +01:00
|
|
|
writer.Write(DataCenter.Port);
|
2016-04-18 12:50:57 +02:00
|
|
|
|
2016-09-24 15:38:26 +02:00
|
|
|
if (TLUser != null)
|
2016-04-18 12:50:57 +02:00
|
|
|
{
|
|
|
|
|
writer.Write(1);
|
|
|
|
|
writer.Write(SessionExpires);
|
2016-09-24 15:38:26 +02:00
|
|
|
ObjectUtils.SerializeObject(TLUser, writer);
|
2016-04-18 12:50:57 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
writer.Write(0);
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-25 07:40:24 +01:00
|
|
|
Serializers.Bytes.Write(writer, AuthKey.Data);
|
2016-04-18 12:50:57 +02:00
|
|
|
|
|
|
|
|
return stream.ToArray();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Session FromBytes(byte[] buffer, ISessionStore store, string sessionUserId)
|
|
|
|
|
{
|
|
|
|
|
using (var stream = new MemoryStream(buffer))
|
|
|
|
|
using (var reader = new BinaryReader(stream))
|
|
|
|
|
{
|
|
|
|
|
var id = reader.ReadUInt64();
|
|
|
|
|
var sequence = reader.ReadInt32();
|
|
|
|
|
var salt = reader.ReadUInt64();
|
|
|
|
|
var lastMessageId = reader.ReadInt64();
|
|
|
|
|
var timeOffset = reader.ReadInt32();
|
2020-01-25 07:40:24 +01:00
|
|
|
var serverAddress = Serializers.String.Read(reader);
|
2016-04-18 12:50:57 +02:00
|
|
|
var port = reader.ReadInt32();
|
|
|
|
|
|
|
|
|
|
var isAuthExsist = reader.ReadInt32() == 1;
|
|
|
|
|
int sessionExpires = 0;
|
2016-09-24 15:38:26 +02:00
|
|
|
TLUser TLUser = null;
|
2016-04-18 12:50:57 +02:00
|
|
|
if (isAuthExsist)
|
|
|
|
|
{
|
|
|
|
|
sessionExpires = reader.ReadInt32();
|
2016-09-24 15:38:26 +02:00
|
|
|
TLUser = (TLUser)ObjectUtils.DeserializeObject(reader);
|
2016-04-18 12:50:57 +02:00
|
|
|
}
|
|
|
|
|
|
2020-01-25 07:40:24 +01:00
|
|
|
var authData = Serializers.Bytes.Read(reader);
|
2019-02-10 13:53:46 +01:00
|
|
|
var defaultDataCenter = new DataCenter (serverAddress, port);
|
2016-04-18 12:50:57 +02:00
|
|
|
|
|
|
|
|
return new Session(store)
|
|
|
|
|
{
|
|
|
|
|
AuthKey = new AuthKey(authData),
|
|
|
|
|
Id = id,
|
|
|
|
|
Salt = salt,
|
|
|
|
|
Sequence = sequence,
|
|
|
|
|
LastMessageId = lastMessageId,
|
|
|
|
|
TimeOffset = timeOffset,
|
|
|
|
|
SessionExpires = sessionExpires,
|
2016-09-24 15:38:26 +02:00
|
|
|
TLUser = TLUser,
|
2016-04-18 12:50:57 +02:00
|
|
|
SessionUserId = sessionUserId,
|
2019-02-10 13:53:46 +01:00
|
|
|
DataCenter = defaultDataCenter,
|
2016-04-18 12:50:57 +02:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Save()
|
|
|
|
|
{
|
2020-01-31 07:39:19 +01:00
|
|
|
store.Save(this);
|
2016-04-18 12:50:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Session TryLoadOrCreateNew(ISessionStore store, string sessionUserId)
|
|
|
|
|
{
|
2019-02-10 13:53:46 +01:00
|
|
|
var defaultDataCenter = new DataCenter (defaultConnectionAddress, defaultConnectionPort);
|
|
|
|
|
|
2016-09-06 17:20:06 +02:00
|
|
|
return store.Load(sessionUserId) ?? new Session(store)
|
2016-04-18 12:50:57 +02:00
|
|
|
{
|
2016-09-06 17:20:06 +02:00
|
|
|
Id = GenerateRandomUlong(),
|
|
|
|
|
SessionUserId = sessionUserId,
|
2019-02-10 13:53:46 +01:00
|
|
|
DataCenter = defaultDataCenter,
|
2016-09-06 17:20:06 +02:00
|
|
|
};
|
2016-04-18 12:50:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static ulong GenerateRandomUlong()
|
|
|
|
|
{
|
|
|
|
|
var random = new Random();
|
|
|
|
|
ulong rand = (((ulong)random.Next()) << 32) | ((ulong)random.Next());
|
|
|
|
|
return rand;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public long GetNewMessageId()
|
|
|
|
|
{
|
|
|
|
|
long time = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds);
|
|
|
|
|
long newMessageId = ((time / 1000 + TimeOffset) << 32) |
|
|
|
|
|
((time % 1000) << 22) |
|
|
|
|
|
(random.Next(524288) << 2); // 2^19
|
|
|
|
|
// [ unix timestamp : 32 bit] [ milliseconds : 10 bit ] [ buffer space : 1 bit ] [ random : 19 bit ] [ msg_id type : 2 bit ] = [ msg_id : 64 bit ]
|
|
|
|
|
|
|
|
|
|
if (LastMessageId >= newMessageId)
|
|
|
|
|
{
|
|
|
|
|
newMessageId = LastMessageId + 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LastMessageId = newMessageId;
|
|
|
|
|
return newMessageId;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-09-28 04:01:17 +02:00
|
|
|
}
|