Detect arbitrary negative HTTP error codes

This commit is contained in:
Lonami Exo 2018-10-12 19:47:40 +02:00
parent cca7055fcf
commit 6e77f583f1
5 changed files with 28 additions and 20 deletions

View File

@ -8,7 +8,7 @@ from threading import Thread
from .common import ( from .common import (
ReadCancelledError, TypeNotFoundError, InvalidChecksumError, ReadCancelledError, TypeNotFoundError, InvalidChecksumError,
BrokenAuthKeyError, SecurityError, CdnFileTamperedError, MultiError InvalidBufferError, SecurityError, CdnFileTamperedError, MultiError
) )
# This imports the base errors too, as they're imported there # This imports the base errors too, as they're imported there

View File

@ -1,4 +1,6 @@
"""Errors not related to the Telegram API itself""" """Errors not related to the Telegram API itself"""
import struct
from ..tl import TLRequest from ..tl import TLRequest
@ -39,14 +41,21 @@ class InvalidChecksumError(Exception):
self.valid_checksum = valid_checksum self.valid_checksum = valid_checksum
class BrokenAuthKeyError(Exception): class InvalidBufferError(BufferError):
""" """
Occurs when the authorization key for a data center is not valid. Occurs when the buffer is invalid, and may contain an HTTP error code.
For instance, 404 means "forgotten/broken authorization key", while
""" """
def __init__(self): def __init__(self, payload):
super().__init__( self.payload = payload
'The authorization key is broken, and it must be reset.' if len(payload) == 4:
) self.code = -struct.unpack('<i', payload)[0]
super().__init__(
'Invalid response buffer (HTTP code {})'.format(self.code))
else:
self.code = None
super().__init__(
'Invalid response buffer (too short {})'.format(self.payload))
class SecurityError(Exception): class SecurityError(Exception):

View File

@ -5,7 +5,7 @@ in plain text, when no authorization key has been created yet.
import struct import struct
from .mtprotostate import MTProtoState from .mtprotostate import MTProtoState
from ..errors import BrokenAuthKeyError from ..errors import InvalidBufferError
from ..extensions import BinaryReader from ..extensions import BinaryReader
@ -34,9 +34,8 @@ class MTProtoPlainSender:
) )
body = await self._connection.recv() body = await self._connection.recv()
if body == b'l\xfe\xff\xff': # -404 little endian signed if len(body) < 8:
# Broken authorization, must reset the auth key raise InvalidBufferError(body)
raise BrokenAuthKeyError()
with BinaryReader(body) as reader: with BinaryReader(body) as reader:
auth_key_id = reader.read_long() auth_key_id = reader.read_long()

View File

@ -9,7 +9,7 @@ from .requeststate import RequestState
from ..tl.tlobject import TLRequest from ..tl.tlobject import TLRequest
from .. import utils from .. import utils
from ..errors import ( from ..errors import (
BadMessageError, BrokenAuthKeyError, SecurityError, TypeNotFoundError, BadMessageError, InvalidBufferError, SecurityError, TypeNotFoundError,
InvalidChecksumError, rpc_message_to_error InvalidChecksumError, rpc_message_to_error
) )
from ..extensions import BinaryReader from ..extensions import BinaryReader
@ -382,8 +382,12 @@ class MTProtoSender:
) )
except asyncio.CancelledError: except asyncio.CancelledError:
return return
except (BrokenAuthKeyError, BufferError): except BufferError as e:
__log__.info('Broken authorization key; resetting') if isinstance(e, InvalidBufferError) and e.code == 404:
__log__.info('Broken authorization key; resetting')
else:
__log__.warning('Invalid buffer %s', e)
self._connection._state.auth_key = None self._connection._state.auth_key = None
self._start_reconnect() self._start_reconnect()
return return

View File

@ -5,7 +5,7 @@ import time
from hashlib import sha256 from hashlib import sha256
from ..crypto import AES from ..crypto import AES
from ..errors import SecurityError, BrokenAuthKeyError from ..errors import SecurityError, InvalidBufferError
from ..extensions import BinaryReader from ..extensions import BinaryReader
from ..tl.core import TLMessage from ..tl.core import TLMessage
from ..tl.functions import InvokeAfterMsgRequest from ..tl.functions import InvokeAfterMsgRequest
@ -114,11 +114,7 @@ class MTProtoState:
Inverse of `encrypt_message_data` for incoming server messages. Inverse of `encrypt_message_data` for incoming server messages.
""" """
if len(body) < 8: if len(body) < 8:
# TODO If len == 4, raise HTTPErrorCode(-little endian int) raise InvalidBufferError(body)
if body == b'l\xfe\xff\xff':
raise BrokenAuthKeyError()
else:
raise BufferError("Can't decode packet ({})".format(body))
# TODO Check salt, session_id and sequence_number # TODO Check salt, session_id and sequence_number
key_id = struct.unpack('<Q', body[:8])[0] key_id = struct.unpack('<Q', body[:8])[0]