Save dc_id instead layer and salt in the session file

Server salts change every 30 minutes after all, so keeping them
in the long-term storage session file doesn't make much sense.

Saving the layer doesn't make sense either, as it was only used
to know whether to init connection or not, but it should be done
always.
This commit is contained in:
Lonami Exo 2017-12-28 01:04:11 +01:00
parent 21e5f0b547
commit ab07f0220a
3 changed files with 26 additions and 64 deletions

View File

@ -39,6 +39,7 @@ from .update_state import UpdateState
from .utils import get_appropriated_part_size from .utils import get_appropriated_part_size
DEFAULT_DC_ID = 4
DEFAULT_IPV4_IP = '149.154.167.51' DEFAULT_IPV4_IP = '149.154.167.51'
DEFAULT_IPV6_IP = '[2001:67c:4e8:f002::a]' DEFAULT_IPV6_IP = '[2001:67c:4e8:f002::a]'
DEFAULT_PORT = 443 DEFAULT_PORT = 443
@ -101,9 +102,11 @@ class TelegramBareClient:
# ':' in session.server_address is True if it's an IPv6 address # ':' in session.server_address is True if it's an IPv6 address
if (not session.server_address or if (not session.server_address or
(':' in session.server_address) != use_ipv6): (':' in session.server_address) != use_ipv6):
session.port = DEFAULT_PORT session.set_dc(
session.server_address = \ DEFAULT_DC_ID,
DEFAULT_IPV6_IP if self._use_ipv6 else DEFAULT_IPV4_IP DEFAULT_IPV6_IP if self._use_ipv6 else DEFAULT_IPV4_IP,
DEFAULT_PORT
)
self.session = session self.session = session
self.api_id = int(api_id) self.api_id = int(api_id)
@ -294,8 +297,7 @@ class TelegramBareClient:
dc = self._get_dc(new_dc) dc = self._get_dc(new_dc)
__log__.info('Reconnecting to new data center %s', dc) __log__.info('Reconnecting to new data center %s', dc)
self.session.server_address = dc.ip_address self.session.set_dc(dc.id, dc.ip_address, dc.port)
self.session.port = dc.port
# auth_key's are associated with a server, which has now changed # auth_key's are associated with a server, which has now changed
# so it's not valid anymore. Set to None to force recreating it. # so it's not valid anymore. Set to None to force recreating it.
self.session.auth_key = None self.session.auth_key = None
@ -363,8 +365,7 @@ class TelegramBareClient:
# Construct this session with the connection parameters # Construct this session with the connection parameters
# (system version, device model...) from the current one. # (system version, device model...) from the current one.
session = Session(self.session) session = Session(self.session)
session.server_address = dc.ip_address session.set_dc(dc.id, dc.ip_address, dc.port)
session.port = dc.port
self._exported_sessions[dc_id] = session self._exported_sessions[dc_id] = session
__log__.info('Creating exported new client') __log__.info('Creating exported new client')
@ -390,8 +391,7 @@ class TelegramBareClient:
if not session: if not session:
dc = self._get_dc(cdn_redirect.dc_id, cdn=True) dc = self._get_dc(cdn_redirect.dc_id, cdn=True)
session = Session(self.session) session = Session(self.session)
session.server_address = dc.ip_address session.set_dc(dc.id, dc.ip_address, dc.port)
session.port = dc.port
self._exported_sessions[cdn_redirect.dc_id] = session self._exported_sessions[cdn_redirect.dc_id] = session
__log__.info('Creating new CDN client') __log__.info('Creating new CDN client')
@ -494,7 +494,7 @@ class TelegramBareClient:
def _invoke(self, sender, call_receive, update_state, *requests): def _invoke(self, sender, call_receive, update_state, *requests):
# We need to specify the new layer (by initializing a new # We need to specify the new layer (by initializing a new
# connection) if it has changed from the latest known one. # connection) if it has changed from the latest known one.
init_connection = self.session.layer != LAYER init_connection = False # TODO Only first call
try: try:
# Ensure that we start with no previous errors (i.e. resending) # Ensure that we start with no previous errors (i.e. resending)
@ -553,12 +553,6 @@ class TelegramBareClient:
# User never called .connect(), so raise this error. # User never called .connect(), so raise this error.
raise raise
if init_connection:
# We initialized the connection successfully, even if
# a request had an RPC error we have invoked it fine.
self.session.layer = LAYER
self.session.save()
try: try:
raise next(x.rpc_error for x in requests if x.rpc_error) raise next(x.rpc_error for x in requests if x.rpc_error)
except StopIteration: except StopIteration:

View File

@ -67,6 +67,7 @@ class Session:
self._sequence = 0 self._sequence = 0
self.time_offset = 0 self.time_offset = 0
self._last_msg_id = 0 # Long self._last_msg_id = 0 # Long
self.salt = 0 # Long
# Cross-thread safety # Cross-thread safety
self._seq_no_lock = Lock() self._seq_no_lock = Lock()
@ -74,11 +75,10 @@ class Session:
self._db_lock = Lock() self._db_lock = Lock()
# These values will be saved # These values will be saved
self._dc_id = 0
self._server_address = None self._server_address = None
self._port = None self._port = None
self._auth_key = None self._auth_key = None
self._layer = 0
self._salt = 0 # Signed long
# Migrating from .json -> SQL # Migrating from .json -> SQL
entities = self._check_migrate_json() entities = self._check_migrate_json()
@ -97,8 +97,7 @@ class Session:
# These values will be saved # These values will be saved
c.execute('select * from sessions') c.execute('select * from sessions')
self._server_address, self._port, key, \ self._dc_id, self._server_address, self._port, key, = c.fetchone()
self._layer, self._salt = c.fetchone()
from ..crypto import AuthKey from ..crypto import AuthKey
self._auth_key = AuthKey(data=key) self._auth_key = AuthKey(data=key)
@ -108,12 +107,11 @@ class Session:
c.execute("create table version (version integer)") c.execute("create table version (version integer)")
c.execute( c.execute(
"""create table sessions ( """create table sessions (
dc_id integer primary key,
server_address text, server_address text,
port integer, port integer,
auth_key blob, auth_key blob
layer integer, ) without rowid"""
salt integer
)"""
) )
c.execute( c.execute(
"""create table entities ( """create table entities (
@ -142,13 +140,6 @@ class Session:
self.delete() # Delete JSON file to create database self.delete() # Delete JSON file to create database
self._port = data.get('port', self._port) self._port = data.get('port', self._port)
self._salt = data.get('salt', self._salt)
# Keep while migrating from unsigned to signed salt
if self._salt > 0:
self._salt = struct.unpack(
'q', struct.pack('Q', self._salt))[0]
self._layer = data.get('layer', self._layer)
self._server_address = \ self._server_address = \
data.get('server_address', self._server_address) data.get('server_address', self._server_address)
@ -169,24 +160,20 @@ class Session:
# Data from sessions should be kept as properties # Data from sessions should be kept as properties
# not to fetch the database every time we need it # not to fetch the database every time we need it
def set_dc(self, dc_id, server_address, port):
self._dc_id = dc_id
self._server_address = server_address
self._port = port
self._update_session_table()
@property @property
def server_address(self): def server_address(self):
return self._server_address return self._server_address
@server_address.setter
def server_address(self, value):
self._server_address = value
self._update_session_table()
@property @property
def port(self): def port(self):
return self._port return self._port
@port.setter
def port(self, value):
self._port = value
self._update_session_table()
@property @property
def auth_key(self): def auth_key(self):
return self._auth_key return self._auth_key
@ -196,34 +183,15 @@ class Session:
self._auth_key = value self._auth_key = value
self._update_session_table() self._update_session_table()
@property
def layer(self):
return self._layer
@layer.setter
def layer(self, value):
self._layer = value
self._update_session_table()
@property
def salt(self):
return self._salt
@salt.setter
def salt(self, value):
self._salt = value
self._update_session_table()
def _update_session_table(self): def _update_session_table(self):
with self._db_lock: with self._db_lock:
c = self._conn.cursor() c = self._conn.cursor()
c.execute('delete from sessions') c.execute('delete from sessions')
c.execute('insert into sessions values (?,?,?,?,?)', ( c.execute('insert into sessions values (?,?,?,?)', (
self._dc_id,
self._server_address, self._server_address,
self._port, self._port,
self._auth_key.key if self._auth_key else b'', self._auth_key.key if self._auth_key else b''
self._layer,
self._salt
)) ))
c.close() c.close()

View File

@ -18,7 +18,7 @@ class HigherLevelTests(unittest.TestCase):
@staticmethod @staticmethod
def test_cdn_download(): def test_cdn_download():
client = TelegramClient(None, api_id, api_hash) client = TelegramClient(None, api_id, api_hash)
client.session.server_address = '149.154.167.40' client.session.set_dc(0, '149.154.167.40', 80)
assert client.connect() assert client.connect()
try: try: