From 2e5304e84bc1c8232ccdb339e2e6362501e347ea Mon Sep 17 00:00:00 2001 From: Arne Zellentin Date: Sun, 7 Feb 2021 18:53:10 +0100 Subject: [PATCH] fix: uncaught exception while connecting The call to socket.connect() has been moved to a thread which keeps trying until connected. --- custom_components/badconga/app/client.py | 21 ++++++++--- custom_components/badconga/app/conga.py | 4 +-- custom_components/badconga/app/socket.py | 45 ++++++++++++++++++------ 3 files changed, 52 insertions(+), 18 deletions(-) diff --git a/custom_components/badconga/app/client.py b/custom_components/badconga/app/client.py index 0b1e3f8..a3af852 100644 --- a/custom_components/badconga/app/client.py +++ b/custom_components/badconga/app/client.py @@ -16,14 +16,20 @@ class Client(Evented): """ Client """ + + # pylint: disable=too-many-instance-attributes + def __init__(self): super().__init__() + self.email = None + self.password = None self.session_id = None self.timer = None self.device = Device() self.builder = Builder() self.map = Map() self.socket = Socket(HOST, PORT) + self.socket.on('connect', self.on_connect) self.socket.on('recv', self.on_recv) self.socket.on('disconnect', self.on_disconnect) self.on('login', self.on_login) @@ -219,12 +225,17 @@ def set_session(self, session_id, user_id, device_id): self.builder.device_id = device_id self.session_id = session_id - def login(self, email, password): - """ login """ - self.socket.connect() + def connect(self, email, password): + """ connect """ + self.email = email + self.password = password + self.socket.start_connect() + + def on_connect(self): + """ on_connect """ data = schema_pb2.CMSG_USER_LOGIN() - data.email = email - data.password = password + data.email = self.email + data.password = self.password data.unk1 = 1003 self.send('CMSG_USER_LOGIN', data) diff --git a/custom_components/badconga/app/conga.py b/custom_components/badconga/app/conga.py index f2c67f1..38cd11c 100644 --- a/custom_components/badconga/app/conga.py +++ b/custom_components/badconga/app/conga.py @@ -40,7 +40,7 @@ def loop(self): self.reschedule() return None if not self.is_logged: - return self.client.login(self.email, self.password) + return self.client.connect(self.email, self.password) if not self.is_device_connected: return self.client.connect_device() if not self.is_running: @@ -94,7 +94,7 @@ def on_device_inuse(self): # methods def start(self): - """ login """ + """ start """ self.is_running = True self.loop() diff --git a/custom_components/badconga/app/socket.py b/custom_components/badconga/app/socket.py index a59dc19..0b9fcde 100644 --- a/custom_components/badconga/app/socket.py +++ b/custom_components/badconga/app/socket.py @@ -3,6 +3,7 @@ import socket import logging import struct +import time from .evented import Evented logger = logging.getLogger(__name__) @@ -13,27 +14,49 @@ def __init__(self, host, port): super().__init__() self.host = host self.port = port + self.is_connecting = False self.is_connected = False - self.thread = None + self.connect_thread = None + self.recv_thread = None self.sock = None def __del__(self): self.disconnect() + def start_connect(self): + """ start_connect """ + self.is_connecting = True + self.connect_thread = threading.Thread(target=self.connect) + self.connect_thread.start() + def connect(self): """ connect """ - if not self.is_connected: + while self.is_connecting and not self.is_connected: logger.debug('connecting to %s:%s...', self.host, self.port) - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.settimeout(90.0) - self.sock.connect((self.host, self.port)) + try: + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.settimeout(90.0) + self.sock.connect((self.host, self.port)) + except socket.error as error: + logger.debug('connect error: %s', error) + time.sleep(60) + continue self.is_connected = True - self.thread = threading.Thread(target=self.handle) - self.thread.start() + self.is_connecting = False + self.recv_thread = threading.Thread(target=self.handle) + self.recv_thread.start() self.trigger('connect') def disconnect(self): """ disconnect """ + if self.connect_thread: + self.is_connecting = False + if self.connect_thread != threading.current_thread(): + try: + self.connect_thread.join() + except RuntimeError: + pass + self.connect_thread = None if self.is_connected: logger.debug('disconnecting...') self.is_connected = False @@ -43,15 +66,15 @@ def disconnect(self): self.sock.close() except socket.error: pass - if self.thread: - if self.thread != threading.current_thread(): + if self.recv_thread: + if self.recv_thread != threading.current_thread(): logger.debug('waiting for thread to close...') try: - self.thread.join() + self.recv_thread.join() except RuntimeError: pass self.sock = None - self.thread = None + self.recv_thread = None self.trigger('disconnect') def send(self, data: bytes):