Beispiel #1
0
    def __connectToServer(self):
        # Create the connection manager to manage all communcation to the server
        self.connectionManager = ConnectionManager(self.nick, (self.turn, self.port), self.chatWindow.postMessage, self.chatWindow.newClient, self.chatWindow.clientReady, self.chatWindow.smpRequest, self.chatWindow.handleError)
        self.chatWindow.connectionManager = self.connectionManager

        # Start the connect thread
        self.connectThread = qtThreads.QtServerConnectThread(self.connectionManager, self.__postConnect, self.__connectFailure)
        self.connectThread.start()

        # Show the waiting dialog
        self.waitingDialog = QWaitingDialog(self.chatWindow, "Connecting to server...")
        self.waitingDialog.show()
Beispiel #2
0
    def __waitForClient(self):
        # Start the accept thread
        self.acceptThread = qtThreads.QtServerAcceptThread(self.server, self.crypto, self.__postAccept)
        self.acceptThread.start()

        # Show the waiting dialog
        self.waitingDialog = QWaitingDialog(self.chatWindow, "Waiting for connection...", self.isLightTheme, self.__userClosedWaitingDialog, showIP=True)
        self.waitingDialog.show()
Beispiel #3
0
    def __connectToServer(self):
        # Create the client object to use for the connection
        self.client = Client(constants.MODE_CLIENT, (self.host, self.port), crypto=self.crypto)

        # Start the connect thread
        self.connectThread = qtThreads.QtServerConnectThread(self.client, self.__postConnect, self.__connectFailure)
        self.connectThread.start()

        # Show the waiting dialog
        self.waitingDialog = QWaitingDialog(self.chatWindow, "Connecting to server...", self.isLightTheme, self.__userClosedWaitingDialog)
        self.waitingDialog.show()
Beispiel #4
0
class QtUI(QApplication):
    def __init__(self, argv, nick, turn, port):
        QApplication.__init__(self, argv)

        self.nick = nick
        self.turn = turn
        self.port = port
        self.isEventLoopRunning = False

        qtUtils.setIsLightTheme(self.palette().color(QPalette.Window))

        self.aboutToQuit.connect(self.stop)


    def start(self):
        # Start a timer to allow for ctrl+c handling
        self.timer = QTimer()
        self.timer.start(500)
        self.timer.timeout.connect(lambda: None)

        # Show the login window and get the nick
        nick = QLoginWindow.getNick(QWidget(), self.nick)

        # If the nick is None, the user closed the window so we should quit the app
        if nick is None:
            qtUtils.exitApp()
        else:
            self.nick = str(nick)

        # Show the chat window
        self.chatWindow = QChatWindow(self.restart)
        self.chatWindow.show()

        self.__connectToServer()

        # Don't start the event loop again if it's already running
        if not self.isEventLoopRunning:
            self.isEventLoopRunning = True
            self.exec_()


    def stop(self):
        if hasattr(self, 'connectionManager'):
            self.connectionManager.disconnectFromServer()

        # Give the send thread time to get the disconnect messages out before exiting
        # and killing the thread
        time.sleep(.25)

        self.quit()


    def restart(self):
        if hasattr(self, 'connectionManager'):
            self.connectionManager.disconnectFromServer()

        self.closeAllWindows()
        if hasattr(self, 'chatWindow'):
            del self.chatWindow

        self.start()


    def __connectToServer(self):
        # Create the connection manager to manage all communcation to the server
        self.connectionManager = ConnectionManager(self.nick, (self.turn, self.port), self.chatWindow.postMessage, self.chatWindow.newClient, self.chatWindow.clientReady, self.chatWindow.smpRequest, self.chatWindow.handleError)
        self.chatWindow.connectionManager = self.connectionManager

        # Start the connect thread
        self.connectThread = qtThreads.QtServerConnectThread(self.connectionManager, self.__postConnect, self.__connectFailure)
        self.connectThread.start()

        # Show the waiting dialog
        self.waitingDialog = QWaitingDialog(self.chatWindow, "Connecting to server...")
        self.waitingDialog.show()


    @pyqtSlot()
    def __postConnect(self):
        self.waitingDialog.close()
        self.chatWindow.connectedToServer()


    @pyqtSlot(str)
    def __connectFailure(self, errorMessage):
        # Show a more friendly error if the connection was refused (errno 111)
        if errorMessage.contains('Errno 111'):
            errorMessage = "Unable to contact the server. Try again later."

        QMessageBox.critical(self.chatWindow, errors.FAILED_TO_CONNECT, errorMessage)
        self.restart()
Beispiel #5
0
class QtUI(QApplication):
    def __init__(self, argv, mode, port, host):
        QApplication.__init__(self, argv)

        self.mode = mode
        self.port = port
        self.host = host
        self.isEventLoopRunning = False
        self.connectedToClient = False
        self.isLightTheme = qtUtils.isLightTheme(self.palette().color(QPalette.Window))

        self.aboutToQuit.connect(self.stop)


    def start(self):
        self.timer = QTimer()
        self.timer.start(500)
        self.timer.timeout.connect(lambda: None)

        # Show mode dialog if a mode wasn't given
        if self.mode is None:
            self.mode = QModeDialog.getMode(self.isLightTheme)
            # If the user closed the mode dialog by not selected a mode, stop the app
            if self.mode is None:
                qtUtils.exitApp()

        # Show the chat window
        self.chatWindow = QChatWindow(None, None, self.isLightTheme)
        self.chatWindow.show()

        self.__loadOrGenerateKepair()

        if self.mode == constants.MODE_SERVER:
            self.__startServer()
            self.__waitForClient()
        elif self.mode == constants.MODE_CLIENT:
            # Get the host if not given
            if self.host is None:
                self.host, ok = QInputDialog.getText(self.chatWindow, "Hostname", "Host:")
                if not ok:
                    self.__restart()
                    return

            self.__connectToServer()

        if not self.isEventLoopRunning:
            self.isEventLoopRunning = True
            self.exec_()


    def stop(self):
        self.__endConnections()
        self.quit()


    def __restart(self):
        self.__endConnections()
        self.__restartHelper()
        self.start()


    def __endConnections(self):
        if hasattr(self, 'acceptThread'):
            self.acceptThread.quit()
        elif hasattr(self, 'connectThread'):
            self.connectThread.quit()

        if hasattr(self, 'sendThread'):
            self.sendThread.quit()

        if hasattr(self, 'recvThread'):
            self.recvThread.quit()

        # If a client is connected, try to end the connection gracefully
        if hasattr(self, 'client'):
            self.client.disconnect()

        if hasattr(self, 'server'):
            self.server.stop()


    def __restartHelper(self):
        self.mode = None
        self.host = None

        self.closeAllWindows()

        if hasattr(self, 'waitingDialog'):
            del self.waitingDialog

        if hasattr(self, 'chatWindow'):
            del self.chatWindow


    def __loadOrGenerateKepair(self):
        self.crypto = Crypto()
        if utils.doesSavedKeypairExist():
            while(True):
                passphrase = qtUtils.getKeypairPassphrase(self.isLightTheme)

                # Restart the application if the user did not provide a passphrase
                if passphrase is None:
                    self.__restart()
                    return

                try:
                    utils.loadKeypair(self.crypto, passphrase)
                    break
                except exceptions.CryptoError:
                    QMessageBox.warning(self.chatWindow, errors.BAD_PASSPHRASE, errors.BAD_PASSPHRASE_VERBOSE)

            # We still need to generate an AES key
            self.crypto.generateAESKey()
        else:
            self.crypto.generateKeys()


    def __startServer(self):
        try:
            self.server = Server()
            self.server.start(int(self.port))
        except exceptions.NetworkError as ne:
            QMessageBox.critical(self.chatWindow, errors.FAILED_TO_START_SERVER, errors.FAILED_TO_START_SERVER + ": " + str(ne))
            self.__restart()


    def __waitForClient(self):
        # Start the accept thread
        self.acceptThread = qtThreads.QtServerAcceptThread(self.server, self.crypto, self.__postAccept)
        self.acceptThread.start()

        # Show the waiting dialog
        self.waitingDialog = QWaitingDialog(self.chatWindow, "Waiting for connection...", self.isLightTheme, self.__userClosedWaitingDialog, showIP=True)
        self.waitingDialog.show()


    def __connectToServer(self):
        # Create the client object to use for the connection
        self.client = Client(constants.MODE_CLIENT, (self.host, self.port), crypto=self.crypto)

        # Start the connect thread
        self.connectThread = qtThreads.QtServerConnectThread(self.client, self.__postConnect, self.__connectFailure)
        self.connectThread.start()

        # Show the waiting dialog
        self.waitingDialog = QWaitingDialog(self.chatWindow, "Connecting to server...", self.isLightTheme, self.__userClosedWaitingDialog)
        self.waitingDialog.show()


    @pyqtSlot(Client)
    def __postAccept(self, client):
        self.connectedToClient = True
        self.client = client
        self.waitingDialog.close()

        # Show the accept dialog
        accept = QAcceptDialog.getAnswer(self.chatWindow, self.client.getHostname())

        # If not accepted, disconnect and wait for a client again
        if not accept:
            self.client.disconnect()
            self.__waitForClient()
            return

        # Do the handshake with the client
        try:
            client.doHandshake()
        except exceptions.NetworkError as ne:
            self.client.disconnect()
            self.__waitForClient()

        self.__startChat()


    @pyqtSlot()
    def __postConnect(self):
        self.connectedToClient = True
        self.waitingDialog.close()
        self.__startChat()


    @pyqtSlot(str)
    def __connectFailure(self, errorMessage):
        QMessageBox.critical(self.chatWindow, errors.FAILED_TO_CONNECT, errorMessage)
        self.__restart()


    @pyqtSlot()
    def __userClosedWaitingDialog(self):
        self.waitingDialog.hide()
        # If the waiting dialog was closed before we connected to the client,
        # it means that the user closed the dialog and we should restart the app
        if not self.connectedToClient:
            self.__restart()


    def __startChat(self):
        # Start the sending and receiving thread
        self.recvThread = qtThreads.QtRecvThread(self.client, self.chatWindow.appendMessage, self.__threadError)
        self.recvThread.start()
        self.sendThread = qtThreads.QtSendThread(self.client, self.__threadError)
        self.sendThread.start()

        self.chatWindow.client = self.client
        self.chatWindow.messageQueue = self.sendThread.messageQueue
        self.chatWindow.showNowChattingMessage()


    @pyqtSlot(str, str)
    def __threadError(self, title, message):
        QMessageBox.critical(self.chatWindow, title, message)
        self.__restart()