Ejemplo n.º 1
0
    def start(self):
        if self.logger_name:
            self.logger = logging.getLogger(self.logger_name)  # noqa
        else:
            self.logger = logging.getLogger(self.__class__.__name__)  # noqa
        self.data = {"size_left": 0, "data": b""}  # noqa
        self.tcpSocket = QTcpSocket(self)  # noqa

        self.tcpSocket.setObjectName("qclient_socket")
        QMetaObject.connectSlotsByName(self)
        self.tcpSocket.setSocketOption(QAbstractSocket.KeepAliveOption, 1)
        self.tcpSocket.connectToHost(QHostAddress(self.ip), self.port,
                                     QIODevice.ReadWrite)
        if not self.tcpSocket.waitForConnected(3000):
            self.failed_to_connect.emit(self.ip, self.port)
            self.tcpSocket.disconnectFromHost()
            self.tcpSocket.close()
            self.logger.error("Failed to connect to {}:{}".format(
                self.ip, self.port))
            return

        self.close_signal.connect(self.close, Qt.BlockingQueuedConnection)
        self.write_signal.connect(self._write)
        self.connect_signal.connect(self._connectTo)
        self.disconnect_signal.connect(self._disconnect)
        self.reconnect_signal.connect(self._reconnect)
Ejemplo n.º 2
0
    def __init__(self, *args, **kwargs):
        super(Client, self).__init__(*args, **kwargs)
        self.loginWidget = LoginWidget()
        self.chatWidget = ChatWidget()
        self.setCentralWidget(self.loginWidget)

        self.socket = QTcpSocket()

        self.setupConnections()
Ejemplo n.º 3
0
    def run(self):
        self.log.debug('Connection id={} is starting'.format(self.conn_id))

        def wait_and_read(n_bytes):
            """
            Convenience function that simplifies reading and checking for stop events, etc.
            Returns a byte string of length n_bytes or None if socket needs to be closed.

            """
            data = b""
            while len(data) < n_bytes:
                if sock.bytesAvailable() == 0:
                    new_data = sock.waitForReadyRead(100)  # wait for 100ms between read attempts
                    if not new_data:
                        if sock.state() != sock.ConnectedState or self.need_to_stop():
                            return None
                        else:
                            continue
                if self.need_to_stop():
                    return None
                new_data = sock.read(n_bytes - len(data))
                if type(new_data) != bytes:
                    new_data = new_data.data()
                data += new_data
            return data

        sock = QTcpSocket(None)
        sock.setSocketDescriptor(self.socketDescriptor)
        sock.waitForConnected()

        while True:
            read_len = wait_and_read(4)
            if not read_len:
                break
            read_len = struct.unpack(">L", read_len)[0]

            data = wait_and_read(read_len)
            if not data:
                break

            if data.startswith(self.internal_prefix):
                self.handle_internal_command(data)
                continue

            try:
                logDict = self.deserialize(data)
                record = LogRecord(logDict)
            except Exception:
                self.log.error('Creating log record failed', exc_info=True)
                continue
            self.new_record.emit(record)

        self.log.debug('Connection id={} is stopping'.format(self.conn_id))
        sock.disconnectFromHost()
        sock.close()
        self.connection_finished.emit(self)
        self.log.debug('Connection id={} has stopped'.format(self.conn_id))
Ejemplo n.º 4
0
    def on_error(self, conn: QTcpSocket):
        """Handle socket errors.

        Args:
            conn (QTcpSocket): Socket object.

        Note:
            Emits error signal.
        """
        device_id = int(conn.objectName())
        e = conn.errorString()
        self.__logger.error("CLIENT-{} Error: {}".format(device_id, e))
        self.error.emit(device_id, str(e))
Ejemplo n.º 5
0
    def run(self) -> None:
        """Run socket manager."""
        self._logger = logging.getLogger(self.__class__.__name__)  # noqa
        self.data = {"size_left": 0, "data": b""}  # noqa
        self.socket = QTcpSocket()  # noqa
        self.socket.setParent(None)  # noqa
        self.socket.setSocketOption(QAbstractSocket.KeepAliveOption, 1)
        if self.socket.setSocketDescriptor(self.socket_descriptor):  # noqa
            self.socket.readyRead.connect(self.on_message)  # noqa
            self.socket.disconnected.connect(self.on_disconnected)  # noqa
            self.socket.error.connect(self.on_error)  # noqa
            self._logger.debug("CLIENT-{} connected to {}:{}".format(self.get_id(),
                                                                     self.socket.peerAddress().toString(),
                                                                     self.socket.peerPort()))

            self.connected.emit(self.get_id(), self.socket.peerAddress().toString(), self.socket.peerPort())
            self.close_signal.connect(self.close, Qt.BlockingQueuedConnection)
            self.write.connect(self._write)
Ejemplo n.º 6
0
class Client(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(Client, self).__init__(*args, **kwargs)
        self.loginWidget = LoginWidget()
        self.chatWidget = ChatWidget()
        self.setCentralWidget(self.loginWidget)

        self.socket = QTcpSocket()

        self.setupConnections()

    def setupConnections(self):
        self.loginWidget.ui.pushButton.clicked.connect(self.connectToHost)
        self.socket.readyRead.connect(self.readData)
        self.socket.error.connect(self.displayConnectionError)
        self.chatWidget.ui.pushButton.clicked.connect(self.sendUserMessage)

    def connectToHost(self):
        hostAddress = self.loginWidget.ui.addressLineEdit.text()
        port = int(self.loginWidget.ui.portLineEdit.text())
        self.socket.connectToHost(hostAddress, port)
        if self.socket.waitForConnected(1000):
            self.nickname = self.loginWidget.ui.nicknameLineEdit.text()
            self.send(f'login {self.nickname}')
            self.loginWidget.setParent(None)
            self.setCentralWidget(self.chatWidget)

    def send(self, message):
        self.socket.write(message.encode('utf-8'))

    def sendUserMessage(self):
        userMessage = self.chatWidget.ui.lineEdit.text()
        message = f'say {userMessage}'
        self.send(message)
        self.chatWidget.ui.lineEdit.clear()
        self.chatWidget.ui.lineEdit.setFocus()

    def readData(self):
        server = self.sender()
        data = server.readLine().data().decode('utf-8').split()
        response = data[0]
        if response == 'say':
            self.chatWidget.ui.textBrowser.append(' '.join(data[1:]))

    def displayConnectionError(self):
        QMessageBox.information(self, '', 'Could not connect to host')

    def closeEvent(self, event):
        self.socket.disconnectFromHost()
Ejemplo n.º 7
0
class _SocketClient(QObject):
    """Keeps socket in separate thread.

    Outgoing signals:
        - disconnected (device_id: int): Client disconnected.
        - connected (device_id: int, ip: str, port: int): Client connected.
        - message (device_id: int, message: bytes): Message from client.
        - error (device_id: int, error: str): Error occured.
        - closed (): Closed successfully.

    Incomming signals:
        - close_signal (): Emit to close connection.
        - write (device_id: int, message: bytes): Emit to send message
          to client with ID in this thread.

    """

    disconnected = Signal(int)
    connected = Signal(int, str, int)
    message = Signal(int, bytes)
    error = Signal(int, str)
    closed = Signal()

    close_signal = Signal()

    write = Signal(bytes)

    def __init__(self, socket_descriptor, client_id):
        super(_SocketClient, self).__init__(None)
        self.socket_descriptor = socket_descriptor
        self.id = int(client_id)

    @Slot()
    def run(self) -> None:
        """Run socket manager."""
        self._logger = logging.getLogger(self.__class__.__name__)  # noqa
        self.data = {"size_left": 0, "data": b""}  # noqa
        self.socket = QTcpSocket()  # noqa
        self.socket.setParent(None)  # noqa
        self.socket.setSocketOption(QAbstractSocket.KeepAliveOption, 1)
        if self.socket.setSocketDescriptor(self.socket_descriptor):  # noqa
            self.socket.readyRead.connect(self.on_message)  # noqa
            self.socket.disconnected.connect(self.on_disconnected)  # noqa
            self.socket.error.connect(self.on_error)  # noqa
            self._logger.debug("CLIENT-{} connected to {}:{}".format(self.get_id(),
                                                                     self.socket.peerAddress().toString(),
                                                                     self.socket.peerPort()))

            self.connected.emit(self.get_id(), self.socket.peerAddress().toString(), self.socket.peerPort())
            self.close_signal.connect(self.close, Qt.BlockingQueuedConnection)
            self.write.connect(self._write)

    @Slot()
    def get_id(self) -> int:
        """Get ID of client."""
        return self.id

    @Slot(bytes)
    def _write(self, message: bytes):
        """Send task to client.

        Args:
            message (bytes): Message to send.
        """
        if self.socket:
            message = struct.pack('!L', len(message)) + message
            self.socket.write(message)
            self.socket.flush()
        else:
            self._logger.warning("Socket not created.")

    @Slot()
    def on_message(self):
        """Handle socket messages.

        Note:
            Emits message signal.
        """
        while self.socket.bytesAvailable():
            size_left = self.data.get("size_left")
            if size_left > 0:
                message = self.socket.read(size_left)
                size_left = size_left - len(message)
                if size_left > 0:
                    self.data["size_left"] = size_left
                    self.data["data"] += message
                else:
                    message = self.data.get("data") + message
                    self.data["size_left"] = 0
                    self.data["data"] = b""
                    self.message.emit(self.get_id(), message)
            else:
                header_size = struct.calcsize('!L')
                header = self.socket.read(header_size)
                if len(header) == 4:
                    msg_size = struct.unpack('!L', header)[0]
                    message = self.socket.read(msg_size)

                    if len(message) < msg_size:
                        msg_size = msg_size - len(message)
                        self.data["data"] = message
                        self.data["size_left"] = msg_size
                    else:
                        self.message.emit(self.get_id(), message)

    @Slot()
    def on_disconnected(self):
        """Handle disconnecting socket.

        Note:
            Emits disconnected signal.
        """
        if self.socket:
            try:
                self._logger.info("CLIENT-{} Disconnected {}: {}:{}".format(self.get_id(), self.socket.peerName(),
                                                                            self.socket.peerAddress().toString(),
                                                                            self.socket.peerPort()))
                self.socket.close()
                self.disconnected.emit(self.get_id())
            except RuntimeError:
                pass

    @Slot()
    def on_error(self):
        """Handle socket errors

        Note:
            Emits error signal.
        """
        e = self.socket.errorString()
        self._logger.error("CLIENT-{} Error: {}".format(self.get_id(), e))
        self.error.emit(self.get_id(), str(e))

    @Slot()
    def close(self):
        """Close connection.

        Note:
            Emits closed signal.
        """
        self.socket.close()
        self.socket.deleteLater()
        self.closed.emit()
Ejemplo n.º 8
0
    def on_connection(self, device_id: int, socket_descriptor: int):
        """Create new QTcpSocket object and setup connection with client.

        Args:
            device_id (int): Socket ID.
            socket_descriptor (int) Socket descriptor.
        Note:
            Emits connected signal.
        """
        socket = QTcpSocket()
        socket.setParent(None)  # noqa
        if socket.setSocketDescriptor(socket_descriptor):  # noqa
            socket.readyRead.connect(lambda: self.on_message(socket))  # noqa
            socket.disconnected.connect(lambda: self.on_disconnected(socket))  # noqa
            socket.error.connect(lambda: self.on_error(socket))  # noqa
            socket.setObjectName(str(device_id))
            self.sockets.append(socket)
            self.__logger.debug("New connection from CLIENT-{} "
                                "IP: {}:{}".format(socket.objectName(),
                                                   socket.peerAddress().toString(),
                                                   socket.peerPort()))
            self.connected.emit(int(socket.objectName()), socket.peerAddress().toString(), socket.peerPort())
Ejemplo n.º 9
0
class _SocketClient(QObject):
    closed = Signal()
    connected = Signal(str, int)
    message = Signal(bytes)
    disconnected = Signal()
    error = Signal(str)
    failed_to_connect = Signal(str, int)

    close_signal = Signal()
    write_signal = Signal(bytes)
    reconnect_signal = Signal()
    connect_signal = Signal(str, int)
    disconnect_signal = Signal()

    def __init__(self, ip: str, port: int, loggerName=None):
        super(_SocketClient, self).__init__(None)
        self.ip = ip
        self.port = port
        self.logger_name = loggerName

    @Slot()
    def start(self):
        if self.logger_name:
            self.logger = logging.getLogger(self.logger_name)  # noqa
        else:
            self.logger = logging.getLogger(self.__class__.__name__)  # noqa
        self.data = {"size_left": 0, "data": b""}  # noqa
        self.tcpSocket = QTcpSocket(self)  # noqa

        self.tcpSocket.setObjectName("qclient_socket")
        QMetaObject.connectSlotsByName(self)
        self.tcpSocket.setSocketOption(QAbstractSocket.KeepAliveOption, 1)
        self.tcpSocket.connectToHost(QHostAddress(self.ip), self.port,
                                     QIODevice.ReadWrite)
        if not self.tcpSocket.waitForConnected(3000):
            self.failed_to_connect.emit(self.ip, self.port)
            self.tcpSocket.disconnectFromHost()
            self.tcpSocket.close()
            self.logger.error("Failed to connect to {}:{}".format(
                self.ip, self.port))
            return

        self.close_signal.connect(self.close, Qt.BlockingQueuedConnection)
        self.write_signal.connect(self._write)
        self.connect_signal.connect(self._connectTo)
        self.disconnect_signal.connect(self._disconnect)
        self.reconnect_signal.connect(self._reconnect)

    @Slot(bytes)
    def _write(self, message: bytes):
        """Write dict to server"""
        message = struct.pack('!L', len(message)) + message
        self.tcpSocket.write(message)
        self.tcpSocket.flush()

    @Slot(int)
    def on_qclient_socket_error(self, error):
        self.logger.error(self.tcpSocket.errorString())
        self.error.emit(error)

    @Slot()
    def on_qclient_socket_connected(self):
        ip = self.tcpSocket.peerAddress().toString()
        port = int(self.tcpSocket.peerPort())
        self.logger.debug("Connected to {}:{}".format(ip, port))
        self.connected.emit(ip, port)

    @Slot()
    def on_qclient_socket_disconnected(self):
        self.logger.info("Disconnected from server")
        self.disconnected.emit()

    @Slot()
    def on_qclient_socket_readyRead(self):
        while self.tcpSocket.bytesAvailable():
            size_left = self.data.get("size_left")
            if size_left > 0:
                message = self.tcpSocket.read(size_left)
                size_left = size_left - len(message)
                if size_left > 0:
                    self.data["size_left"] = size_left
                    self.data["data"] += message
                else:
                    message = self.data.get("data") + message
                    self.data["size_left"] = 0
                    self.data["data"] = b""
                    self.message.emit(message)
            else:
                header_size = struct.calcsize('!L')
                header = self.tcpSocket.read(header_size)
                if len(header) == 4:
                    msg_size = struct.unpack('!L', header)[0]
                    message = self.tcpSocket.read(msg_size)

                    if len(message) < msg_size:
                        msg_size = msg_size - len(message)
                        self.data["data"] = message
                        self.data["size_left"] = msg_size
                    else:
                        self.message.emit(message)

    @Slot(str, int)
    def _connectTo(self, ip: str, port: int):
        self._disconnect()
        self.ip = ip
        self.port = port
        self.start()

    @Slot()
    def _reconnect(self):
        self._disconnect()
        self.start()

    @Slot()
    def _disconnect(self):
        self.tcpSocket.disconnectFromHost()

    @Slot()
    def close(self):
        self._disconnect()
        self.tcpSocket.close()
        self.closed.emit()