diff --git a/telethon/extensions/tcp_client.py b/telethon/extensions/tcp_client.py index 2ccdb0f0..edf6cb4b 100644 --- a/telethon/extensions/tcp_client.py +++ b/telethon/extensions/tcp_client.py @@ -30,19 +30,33 @@ class TcpClient: else: # tuple, list, etc. self._socket.set_proxy(*self._proxy) + self._socket.settimeout(self._timeout) + def connect(self, ip, port): """Connects to the specified IP and port number. 'timeout' must be given in seconds """ - if not self.connected: - if ':' in ip: # IPv6 - mode, address = socket.AF_INET6, (ip, port, 0, 0) - else: - mode, address = socket.AF_INET, (ip, port) + if ':' in ip: # IPv6 + mode, address = socket.AF_INET6, (ip, port, 0, 0) + else: + mode, address = socket.AF_INET, (ip, port) - self._recreate_socket(mode) - self._socket.settimeout(self._timeout) - self._socket.connect(address) + while True: + try: + if not self._socket: + self._recreate_socket(mode) + + self._socket.connect(address) + break # Successful connection, stop retrying to connect + except OSError as e: + # There are some errors that we know how to handle, and + # the loop will allow us to retry + if e.errno == errno.EBADF: + # Bad file descriptor, i.e. socket was closed, set it + # to none to recreate it on the next iteration + self._socket = None + else: + raise def _get_connected(self): return self._socket is not None diff --git a/telethon/network/connection.py b/telethon/network/connection.py index 1426ce78..c79703cf 100644 --- a/telethon/network/connection.py +++ b/telethon/network/connection.py @@ -3,6 +3,8 @@ from datetime import timedelta from zlib import crc32 from enum import Enum +import errno + from ..crypto import AESModeCTR from ..extensions import BinaryWriter, TcpClient from ..errors import InvalidChecksumError @@ -75,9 +77,15 @@ class Connection: setattr(self, 'read', self._read_plain) def connect(self): - self._send_counter = 0 - self.conn.connect(self.ip, self.port) + try: + self.conn.connect(self.ip, self.port) + except OSError as e: + if e.errno == errno.EISCONN: + return # Already connected, no need to re-set everything up + else: + raise + self._send_counter = 0 if self._mode == ConnectionMode.TCP_ABRIDGED: self.conn.write(b'\xef') elif self._mode == ConnectionMode.TCP_INTERMEDIATE: