TLSharp/TLSharp.Core/Session.cs

193 lines
6 KiB
C#
Raw Normal View History

2015-09-28 04:01:17 +02:00
using System;
using System.IO;
2016-09-22 15:31:59 +02:00
using TeleSharp.TL;
2015-09-28 04:01:17 +02:00
using TLSharp.Core.MTProto;
using TLSharp.Core.MTProto.Crypto;
namespace TLSharp.Core
{
2016-04-18 12:50:57 +02:00
public interface ISessionStore
{
void Save(Session session);
Session Load(string sessionUserId);
}
public class FileSessionStore : ISessionStore
{
public void Save(Session session)
{
using (var stream = new FileStream($"{session.SessionUserId}.dat", FileMode.OpenOrCreate))
{
var result = session.ToBytes();
stream.Write(result, 0, result.Length);
}
}
public Session Load(string sessionUserId)
{
var sessionFileName = $"{sessionUserId}.dat";
2016-09-24 15:38:26 +02:00
if (!File.Exists(sessionFileName))
return null;
using (var stream = new FileStream(sessionFileName, 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)
{
return null;
2016-04-18 12:50:57 +02:00
}
}
public class Session
{
private const string defaultConnectionAddress = "91.108.56.165";
private const int defaultConnectionPort = 443;
public string SessionUserId { get; set; }
public string ServerAddress { get; set; }
public int Port { get; set; }
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;
private ISessionStore _store;
private Session(ISessionStore store)
{
random = new Random();
_store = store;
}
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);
Serializers.String.write(writer, ServerAddress);
writer.Write(Port);
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);
}
Serializers.Bytes.write(writer, AuthKey.Data);
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();
var serverAddress = Serializers.String.read(reader);
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
}
var authData = Serializers.Bytes.read(reader);
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,
ServerAddress = serverAddress,
Port = port
};
}
}
public void Save()
{
_store.Save(this);
}
public static Session TryLoadOrCreateNew(ISessionStore store, string sessionUserId)
{
return store.Load(sessionUserId) ?? new Session(store)
2016-04-18 12:50:57 +02:00
{
Id = GenerateRandomUlong(),
SessionUserId = sessionUserId,
ServerAddress = defaultConnectionAddress,
Port = defaultConnectionPort
};
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
}