Esempio n. 1
0
 def __init__(self, line_edit_widget=None, text_widget=None):
     try:
         self.line_edit = line_edit_widget
         self.text_widget= text_widget
         self.socket =QTcpSocket()
     except Exception as e:
         print(e)
Esempio n. 2
0
class TcpClient():
    def __init__(self, line_edit_widget=None, text_widget=None):
        try:
            self.line_edit = line_edit_widget
            self.text_widget= text_widget
            self.socket =QTcpSocket()
        except Exception as e:
            print(e)
        
    def connect_server(self):
        try:
            
            print('inside connect_server')
            self.socket.connectToHost(SERVER_ADDRESS, SERVER_PORT)
        except Exception as e:
            print(e)
        
    def write_data(self):
        try:

            data_byte_array = QByteArray()
            stream =QDataStream(data_byte_array, QIODevice.WriteOnly)
            stream.setVersion(QDataStream.Qt_5_9)
            stream.writeUInt32(0)
            if self.line_edit:
                print('inside write_data')
                stream.writeQString(self.line_edit.text())
            self.socket.write(data_byte_array)
            data_byte_array = None
            if self.line_edit:
                self.line_edit.setText('')
        except Exception as e:
            print(e)
            
    def read_data(self):
        try:
            
            stream =QDataStream(self.socket)
            stream.setVersion(QDataStream.Qt_5_9)
            
            while True:
                if self.socket.bytesAvailable() <= 0:
                    break
                stream.readUInt32()
                text_from_server = stream.readQString()
                if self.text_widget:
                    print('display_text')
                    print(text_from_server)
                    self.text_widget.append(text_from_server)

        except Exception as e:
            print(e)
Esempio n. 3
0
 def __init__(self, parent):
     QObject.__init__(self, parent)
     self._parent = parent
     self._km = parent.key_manager
     self._codec = parent.codec
     self._VERSION = parent.VERSION
     self._qsocket = QTcpSocket(self)
     self._bytestream = None
     self._other_party = None
     self._this_party = None
     self._ip_address = None
     self._port = None
     self._setup()
Esempio n. 4
0
 def __init__(self, parent):
     QObject.__init__(self, parent)
     self._parent = parent
     self._km = parent.key_manager
     self._codec = parent.codec
     self._VERSION = parent.VERSION
     self._qsocket = QTcpSocket(self)
     self._bytestream = None
     self._other_party = None
     self._this_party = None
     self._ip_address = None
     self._port = None
     self._setup()
Esempio n. 5
0
class Client(QObject):
    '''Handles socket.'''

    # Emitted Signals
    comm_update = pyqtSignal([str], name='communication_update')
    chat_update = pyqtSignal([dict], name='chat_update')
    client_connected = pyqtSignal(name='client_connected')
    handshake_succeded = pyqtSignal(name='handshake_succeeded')
    handshake_failed = pyqtSignal(name='handshake_failed')
    msg_ready = pyqtSignal([dict], name='msg_ready')
    comm_error = pyqtSignal(name='comm_error')

    # Signals listened to
    # data_ready = pyqtSignal([str, dict], name='data_ready')
    
    def __init__(self, parent):
        QObject.__init__(self, parent)
        self._parent = parent
        self._km = parent.key_manager
        self._codec = parent.codec
        self._VERSION = parent.VERSION
        self._qsocket = QTcpSocket(self)
        self._bytestream = None
        self._other_party = None
        self._this_party = None
        self._ip_address = None
        self._port = None
        self._setup()
    
    def _setup(self):
        # Ready read
        self._qsocket.readyRead.connect(self._on_ready_read)
        # On connection
        self._qsocket.connected.connect(self._on_connection)
        # On disconnection
        self._qsocket.disconnected.connect(self._on_disconnection)
        # Prime the json generator
        self._msg_buffer = self._add_to_buffer()
        self._msg_buffer.send(None)
        # Connect self.msg_ready
        self.msg_ready.connect(self._dispatch_msg)
        # COnnect connection to _client_handshake_1 to start it off.
        self._qsocket.connected.connect(self._client_handshake_1)
        # Connect error to emit socket update.
        self._qsocket.error.connect(self._on_error)

    def _on_connection(self):
        name = str(self._qsocket.peerName())
        address = self._qsocket.peerAddress().toString()
        self.comm_update.emit('Connected to ' +
                              name +
                              ' (' + address + ')' + '.')
        
    def _on_disconnection(self):
        self.comm_update.emit('Connection terminated.')
        self.comm_error.emit()

    def _on_error(self):
        self.comm_update.emit(self._qsocket.errorString() + '.')
        self.comm_error.emit()
        
    def _on_ready_read(self):
        data = self._qsocket.read(4096)
        self._msg_buffer.send(data)
        # Re-emit readyRead, quasi-recursive.
        if self._qsocket.bytesAvailable():
            self._qsocket.readyRead.emit()

    def _add_to_buffer(self):
        '''Generator created in _setup. Issues data via signal.'''
        # Set up constants.
        opener = '{' #123
        closer = '}' #125
        single_quote = '\'' # 39
        double_quote = '\"' # 34
        self._bytestream = io.BytesIO()
        inside_double_quote = False
        inside_single_quote = False
        opener_count = 0
        closer_count = 0
        # Repeat this loop until end of time.
        while True:
            # Given via generator.send method.
            raw_data = yield
            data = raw_data.decode('utf-8')
            for character in data:
                if character == single_quote:
                    # If True, False. If False, True.
                    inside_single_quote = not inside_single_quote
                if character == double_quote:
                    inside_double_quote = not inside_double_quote
                if inside_single_quote or inside_double_quote:
                    pass
                else:
                    if character == opener:
                        opener_count += 1
                    if character == closer:
                        closer_count += 1
                    if opener_count == closer_count:
                        # Write final character to bytestream
                        self._bytestream.write(character.encode())
                        # Complete JSON message.
                        json_msg = self._bytestream.getvalue().decode('utf-8')
                        msg = json.loads(json_msg)
                        self.msg_ready.emit(msg)
                        # Reset because it's a new message now.
                        self._bytestream = io.BytesIO()
                        inside_double_quote = False
                        inside_single_quote = False
                        opener_count = 0
                        closer_count = 0
                        # Back to "while True" loop
                        continue
                # Write to bytestream
                self._bytestream.write(character.encode())

    def connect_(self, identity, ip_address, port, numeric=True):
        self.comm_update.emit('Connecting.')
        self._this_party = identity
        # If connected, disconnect.
        try:
            if self._qsocket.state == 3:
                self._qsocket.disconnectFromHost()
        except AttributeError:
            pass
        # Connect to host
        if numeric:
            self._qsocket.connectToHost(QHostAddress(ip_address), int(port))
        else:
            self._qsocket.connectToHost(ip_address, int(port))          

    def _dispatch_msg(self, msg_dict):
        '''Route message to correct function.'''
        msg_type = msg_dict['metadata']['type']
        routing_dict = {'text': self._recv_text,
                        'file': None,
                        'server_handshake_1': self._client_handshake_2,
                        'server_handshake_2': self._client_handshake_3}
        function_to_use = routing_dict[msg_type]
        function_to_use(msg_dict)

    def _client_handshake_1(self):
        # Client sends client handshake 1 with list of keys (first msg).
        key_list = [key.name for key in self._km.get_all_keys()]
        data_dict = {'key_list': key_list}
        client_msg_1 = self._create_json_msg('client_handshake_1', data_dict)
        self._qsocket.write(client_msg_1.encode())
    
    def _client_handshake_2(self, msg_dict):
        self._other_party = msg_dict['metadata']['sender']
        shared_keys = msg_dict['data']['shared_keys']
        client_shared_key_data = [self._km.get_key_data(key)
                                  for key
                                  in shared_keys]
        data_dict = {'client_shared_key_data': client_shared_key_data}
        client_msg_2 = self._create_json_msg('client_handshake_2', data_dict)
        self._qsocket.write(client_msg_2.encode())

    def _client_handshake_3(self, msg_dict):
        '''No message.'''
        # Server sends server handshake 2.
        harmonized_data = msg_dict['data']['harmonized_data']
        if not harmonized_data:
            self.comm_update.emit('No shared keys.')
            self._qsocket.disconnectFromHost()
            return False
        for item in harmonized_data:
            if item['sender'] == self._this_party:
                self._km.add_to_outbound(item['name'])
            if item['sender'] == self._other_party:
                self._km.add_to_inbound(item['name'])
        self.handshake_succeded.emit()
        self.comm_update.emit('Client-side handshake complete.')

    def _recv_text(self, msg):
        ciphertext = msg['data']['ciphertext']
        cipherhash = msg['data']['cipherhash']
        plaintext = self._codec.decode(ciphertext, cipherhash)
        msg['plaintext'] = plaintext
        msg['source'] = self._other_party
        self.chat_update.emit(msg)
                 
    def send_text(self, text_data):
        data_bytes = text_data.encode('utf-8')
        ciphertext, cipherhash = self._codec.encode(data_bytes)
        data_dict = {'ciphertext': base64.b64encode(ciphertext).decode(),
                     'cipherhash': base64.b64encode(cipherhash).decode()}
        msg = self._create_json_msg('text', data_dict)
        self._qsocket.write(msg.encode())
        self.chat_update.emit({'source': self._this_party,
                               'content': text_data})
    
    def _send_file(self, file_object):
        pass

    def _recv_file(self, output_path):
        pass

    def _create_json_msg(self, msg_type, data_dict):
        '''Create msg based on template (must be json serialize-able).'''
        base = {'metadata': {'brickton_version': self._VERSION,
                             'sender': self._this_party,
                             'receiver': self._other_party,
                             'timestamp': '{0:.7f}'.format(time.time()),
                             'encoding': 'base64',
                             'type': msg_type},
                'data':{}}
        # Types to check against.
        types = ['text',
                 'file',
                 'server_handshake_1',
                 'server_handshake_2', 
                 'client_handshake_1',
                 'client_handshake_2']
        # Type error checking.
        if not msg_type in types:
            raise BricktonError('Message type not valid.')
        # Keys by type.
        keys_by_type = {'text': ['ciphertext', 'cipherhash'],
                        'file': ['ciphertext', 'cipherhash', 'ciphername'],
                        'server_handshake_1': ['shared_keys'],
                        'server_handshake_2': ['harmonized_data'], 
                        'client_handshake_1': ['key_list'],
                        'client_handshake_2': ['client_shared_key_data']}
        # Keys by type error checking.
        for key in data_dict.keys():
            if not key in keys_by_type[msg_type]:
                raise BricktonError('Improper data for message type supplied.')
        # Populate data dict.
        for key, value in data_dict.items():
            base['data'][key] = value
        # Create and return msg as json.
        msg_string = json.dumps(base)
        return msg_string

    def stop(self):
        self._qsocket.close()
        self.terminate()
Esempio n. 6
0
class Client(QObject):
    '''Handles socket.'''

    # Emitted Signals
    comm_update = pyqtSignal([str], name='communication_update')
    chat_update = pyqtSignal([dict], name='chat_update')
    client_connected = pyqtSignal(name='client_connected')
    handshake_succeded = pyqtSignal(name='handshake_succeeded')
    handshake_failed = pyqtSignal(name='handshake_failed')
    msg_ready = pyqtSignal([dict], name='msg_ready')
    comm_error = pyqtSignal(name='comm_error')

    # Signals listened to
    # data_ready = pyqtSignal([str, dict], name='data_ready')

    def __init__(self, parent):
        QObject.__init__(self, parent)
        self._parent = parent
        self._km = parent.key_manager
        self._codec = parent.codec
        self._VERSION = parent.VERSION
        self._qsocket = QTcpSocket(self)
        self._bytestream = None
        self._other_party = None
        self._this_party = None
        self._ip_address = None
        self._port = None
        self._setup()

    def _setup(self):
        # Ready read
        self._qsocket.readyRead.connect(self._on_ready_read)
        # On connection
        self._qsocket.connected.connect(self._on_connection)
        # On disconnection
        self._qsocket.disconnected.connect(self._on_disconnection)
        # Prime the json generator
        self._msg_buffer = self._add_to_buffer()
        self._msg_buffer.send(None)
        # Connect self.msg_ready
        self.msg_ready.connect(self._dispatch_msg)
        # COnnect connection to _client_handshake_1 to start it off.
        self._qsocket.connected.connect(self._client_handshake_1)
        # Connect error to emit socket update.
        self._qsocket.error.connect(self._on_error)

    def _on_connection(self):
        name = str(self._qsocket.peerName())
        address = self._qsocket.peerAddress().toString()
        self.comm_update.emit('Connected to ' + name + ' (' + address + ')' +
                              '.')

    def _on_disconnection(self):
        self.comm_update.emit('Connection terminated.')
        self.comm_error.emit()

    def _on_error(self):
        self.comm_update.emit(self._qsocket.errorString() + '.')
        self.comm_error.emit()

    def _on_ready_read(self):
        data = self._qsocket.read(4096)
        self._msg_buffer.send(data)
        # Re-emit readyRead, quasi-recursive.
        if self._qsocket.bytesAvailable():
            self._qsocket.readyRead.emit()

    def _add_to_buffer(self):
        '''Generator created in _setup. Issues data via signal.'''
        # Set up constants.
        opener = '{'  #123
        closer = '}'  #125
        single_quote = '\''  # 39
        double_quote = '\"'  # 34
        self._bytestream = io.BytesIO()
        inside_double_quote = False
        inside_single_quote = False
        opener_count = 0
        closer_count = 0
        # Repeat this loop until end of time.
        while True:
            # Given via generator.send method.
            raw_data = yield
            data = raw_data.decode('utf-8')
            for character in data:
                if character == single_quote:
                    # If True, False. If False, True.
                    inside_single_quote = not inside_single_quote
                if character == double_quote:
                    inside_double_quote = not inside_double_quote
                if inside_single_quote or inside_double_quote:
                    pass
                else:
                    if character == opener:
                        opener_count += 1
                    if character == closer:
                        closer_count += 1
                    if opener_count == closer_count:
                        # Write final character to bytestream
                        self._bytestream.write(character.encode())
                        # Complete JSON message.
                        json_msg = self._bytestream.getvalue().decode('utf-8')
                        msg = json.loads(json_msg)
                        self.msg_ready.emit(msg)
                        # Reset because it's a new message now.
                        self._bytestream = io.BytesIO()
                        inside_double_quote = False
                        inside_single_quote = False
                        opener_count = 0
                        closer_count = 0
                        # Back to "while True" loop
                        continue
                # Write to bytestream
                self._bytestream.write(character.encode())

    def connect_(self, identity, ip_address, port, numeric=True):
        self.comm_update.emit('Connecting.')
        self._this_party = identity
        # If connected, disconnect.
        try:
            if self._qsocket.state == 3:
                self._qsocket.disconnectFromHost()
        except AttributeError:
            pass
        # Connect to host
        if numeric:
            self._qsocket.connectToHost(QHostAddress(ip_address), int(port))
        else:
            self._qsocket.connectToHost(ip_address, int(port))

    def _dispatch_msg(self, msg_dict):
        '''Route message to correct function.'''
        msg_type = msg_dict['metadata']['type']
        routing_dict = {
            'text': self._recv_text,
            'file': None,
            'server_handshake_1': self._client_handshake_2,
            'server_handshake_2': self._client_handshake_3
        }
        function_to_use = routing_dict[msg_type]
        function_to_use(msg_dict)

    def _client_handshake_1(self):
        # Client sends client handshake 1 with list of keys (first msg).
        key_list = [key.name for key in self._km.get_all_keys()]
        data_dict = {'key_list': key_list}
        client_msg_1 = self._create_json_msg('client_handshake_1', data_dict)
        self._qsocket.write(client_msg_1.encode())

    def _client_handshake_2(self, msg_dict):
        self._other_party = msg_dict['metadata']['sender']
        shared_keys = msg_dict['data']['shared_keys']
        client_shared_key_data = [
            self._km.get_key_data(key) for key in shared_keys
        ]
        data_dict = {'client_shared_key_data': client_shared_key_data}
        client_msg_2 = self._create_json_msg('client_handshake_2', data_dict)
        self._qsocket.write(client_msg_2.encode())

    def _client_handshake_3(self, msg_dict):
        '''No message.'''
        # Server sends server handshake 2.
        harmonized_data = msg_dict['data']['harmonized_data']
        if not harmonized_data:
            self.comm_update.emit('No shared keys.')
            self._qsocket.disconnectFromHost()
            return False
        for item in harmonized_data:
            if item['sender'] == self._this_party:
                self._km.add_to_outbound(item['name'])
            if item['sender'] == self._other_party:
                self._km.add_to_inbound(item['name'])
        self.handshake_succeded.emit()
        self.comm_update.emit('Client-side handshake complete.')

    def _recv_text(self, msg):
        ciphertext = msg['data']['ciphertext']
        cipherhash = msg['data']['cipherhash']
        plaintext = self._codec.decode(ciphertext, cipherhash)
        msg['plaintext'] = plaintext
        msg['source'] = self._other_party
        self.chat_update.emit(msg)

    def send_text(self, text_data):
        data_bytes = text_data.encode('utf-8')
        ciphertext, cipherhash = self._codec.encode(data_bytes)
        data_dict = {
            'ciphertext': base64.b64encode(ciphertext).decode(),
            'cipherhash': base64.b64encode(cipherhash).decode()
        }
        msg = self._create_json_msg('text', data_dict)
        self._qsocket.write(msg.encode())
        self.chat_update.emit({
            'source': self._this_party,
            'content': text_data
        })

    def _send_file(self, file_object):
        pass

    def _recv_file(self, output_path):
        pass

    def _create_json_msg(self, msg_type, data_dict):
        '''Create msg based on template (must be json serialize-able).'''
        base = {
            'metadata': {
                'brickton_version': self._VERSION,
                'sender': self._this_party,
                'receiver': self._other_party,
                'timestamp': '{0:.7f}'.format(time.time()),
                'encoding': 'base64',
                'type': msg_type
            },
            'data': {}
        }
        # Types to check against.
        types = [
            'text', 'file', 'server_handshake_1', 'server_handshake_2',
            'client_handshake_1', 'client_handshake_2'
        ]
        # Type error checking.
        if not msg_type in types:
            raise BricktonError('Message type not valid.')
        # Keys by type.
        keys_by_type = {
            'text': ['ciphertext', 'cipherhash'],
            'file': ['ciphertext', 'cipherhash', 'ciphername'],
            'server_handshake_1': ['shared_keys'],
            'server_handshake_2': ['harmonized_data'],
            'client_handshake_1': ['key_list'],
            'client_handshake_2': ['client_shared_key_data']
        }
        # Keys by type error checking.
        for key in data_dict.keys():
            if not key in keys_by_type[msg_type]:
                raise BricktonError('Improper data for message type supplied.')
        # Populate data dict.
        for key, value in data_dict.items():
            base['data'][key] = value
        # Create and return msg as json.
        msg_string = json.dumps(base)
        return msg_string

    def stop(self):
        self._qsocket.close()
        self.terminate()