Implementing keep-alive

This commit is contained in:
salarcode 2017-05-03 21:21:11 +04:30
parent c5187ae12b
commit 06337c908b
2 changed files with 80 additions and 20 deletions

View file

@ -12,7 +12,7 @@ namespace TLSharp.Core.Network
private readonly TcpClient _tcpClient;
private int sendCounter = 0;
public TcpTransport(string address, int port, TcpClientConnectionHandler handler = null)
public TcpTransport(string address, int port, bool keepAlive = false, TcpClientConnectionHandler handler = null)
{
if (handler == null)
{
@ -23,6 +23,13 @@ namespace TLSharp.Core.Network
}
else
_tcpClient = handler(address, port);
if (keepAlive)
{
// check every 500 millisecond
// allowed 1 second inactivity
SetKeepAlive(_tcpClient.Client, 1000, 500);
}
}
public async Task Send(byte[] packet)
@ -84,7 +91,58 @@ namespace TLSharp.Core.Network
}
return new TcpMessage(seq, body);
}
}
/// <summary>
/// Setting socket keep-alive
/// </summary>
/// <param name="sock"></param>
/// <param name="time">milliseconds of allowed inactivity</param>
/// <param name="interval">interval milliseconds on keep-alive checks</param>
/// <returns>was successfull?</returns>
private static bool SetKeepAlive(Socket sock, ulong time, ulong interval)
{
// "consts" to help understand calculations
const int bytesperlong = 4; // 32 / 8
const int bitsperbyte = 8;
try
{
// resulting structure
byte[] SIO_KEEPALIVE_VALS = new byte[3 * bytesperlong];
// array to hold input values
ulong[] input = new ulong[3];
// put input arguments in input array
if (time == 0 || interval == 0) // enable disable keep-alive
input[0] = (0UL); // off
else
input[0] = (1UL); // on
input[1] = (time); // time millis
input[2] = (interval); // interval millis
// pack input into byte struct
for (int i = 0; i < input.Length; i++)
{
SIO_KEEPALIVE_VALS[i * bytesperlong + 3] = (byte)(input[i] >> ((bytesperlong - 1) * bitsperbyte) & 0xff);
SIO_KEEPALIVE_VALS[i * bytesperlong + 2] = (byte)(input[i] >> ((bytesperlong - 2) * bitsperbyte) & 0xff);
SIO_KEEPALIVE_VALS[i * bytesperlong + 1] = (byte)(input[i] >> ((bytesperlong - 3) * bitsperbyte) & 0xff);
SIO_KEEPALIVE_VALS[i * bytesperlong + 0] = (byte)(input[i] >> ((bytesperlong - 4) * bitsperbyte) & 0xff);
}
// create bytestruct for result (bytes pending on server socket)
byte[] result = BitConverter.GetBytes(0);
// write SIO_VALS to Socket IOControl
sock.IOControl(IOControlCode.KeepAliveValues, SIO_KEEPALIVE_VALS, result);
}
catch (Exception)
{
return false;
}
return true;
}
public bool IsConnected
{

View file

@ -29,9 +29,10 @@ namespace TLSharp.Core
private Session _session;
private List<TLDcOption> dcOptions;
private TcpClientConnectionHandler _handler;
private bool _keepAlive;
public TelegramClient(int apiId, string apiHash,
ISessionStore store = null, string sessionUserId = "session", TcpClientConnectionHandler handler = null)
ISessionStore store = null, string sessionUserId = "session", bool keepAlive = false, TcpClientConnectionHandler handler = null)
{
if (apiId == default(int))
throw new MissingApiConfigurationException("API_ID");
@ -45,9 +46,10 @@ namespace TLSharp.Core
_apiHash = apiHash;
_apiId = apiId;
_handler = handler;
_keepAlive = keepAlive;
_session = Session.TryLoadOrCreateNew(store, sessionUserId);
_transport = new TcpTransport(_session.ServerAddress, _session.Port, _handler);
_transport = new TcpTransport(_session.ServerAddress, _session.Port, _keepAlive, _handler);
}
public async Task<bool> ConnectAsync(bool reconnect = false)
@ -88,7 +90,7 @@ namespace TLSharp.Core
var dc = dcOptions.First(d => d.id == dcId);
_transport = new TcpTransport(dc.ip_address, dc.port, _handler);
_transport = new TcpTransport(dc.ip_address, dc.port, _keepAlive, _handler);
_session.ServerAddress = dc.ip_address;
_session.Port = dc.port;
@ -110,7 +112,7 @@ namespace TLSharp.Core
var authCheckPhoneRequest = new TLRequestCheckPhone() { phone_number = phoneNumber };
var completed = false;
while(!completed)
while (!completed)
{
try
{
@ -118,7 +120,7 @@ namespace TLSharp.Core
await _sender.Receive(authCheckPhoneRequest);
completed = true;
}
catch(PhoneMigrationException e)
catch (PhoneMigrationException e)
{
await ReconnectToDcAsync(e.DC);
}
@ -324,7 +326,7 @@ namespace TLSharp.Core
_session.AuthKey = authKey;
_session.TimeOffset = timeOffset;
_transport = new TcpTransport(serverAddress, serverPort);
_transport = new TcpTransport(serverAddress, serverPort, _keepAlive);
_session.ServerAddress = serverAddress;
_session.Port = serverPort;
await ConnectAsync();
@ -377,18 +379,18 @@ namespace TLSharp.Core
_session.SessionExpires = int.MaxValue;
_session.Save();
}
public bool IsConnected
{
get
{
if (_transport == null)
return false;
return _transport.IsConnected;
}
}
}
public bool IsConnected
{
get
{
if (_transport == null)
return false;
return _transport.IsConnected;
}
}
public void Dispose()
{
if (_transport != null)