def test_basic_server_transaction(self):
        """Tests the server transaction protocol and logic""" 
    
        db = ContentDB()
        tc = db.add_messages([Message('fubar'), Message('foo'), Message('bar')])
    
        with TestServerHelper() as server_helper, TestClientHelper() as client_helper:
            srv_transaction = ServerTransaction(server_helper.sock, db)
            test_client = SocketTransaction(client_helper.sock, b'\n')
            
            """Run the server transaction in a separate thread to allow client access"""
            thread = threading.Thread(target=srv_transaction.process)
            thread.start()

            """Check greeting from server"""
            rcv = test_client._read()
            self.assertEqual(rcv, Protocol.create_greeting_message(db.id).encode())
            
            """Check response to mdgid list req"""
            test_client._write(Protocol.create_message_id_list_request(tc).encode())
            rcv = test_client._read()
            self.assertEqual(rcv, Protocol.create_message_id_list(tc, None).encode())

            """Check response to mdg req"""
            test_client._write(Protocol.create_message_list_request([msg.id for msg in db.get_messages()]).encode())
            rcv = test_client._read()
            self.assertEqual(rcv, Protocol.create_message_list(db.get_messages()).encode())

            """Wait for server (will time out if no requests)"""
            thread.join(2*TIMEOUT)
    def test_identity_info(self):
        """Test the IdentityInfo class"""

        db = ContentDB(tempfile.NamedTemporaryFile().name)
        id_a = dandelion.identity.generate()
        db.add_identities([id_a])

        # Test creation
        id_info_a = IdentityInfo(db, id_a)
        self.assertEqual(id_info_a.db, db)
        self.assertEqual(id_info_a.id.fingerprint, id_a.fingerprint)
        self.assertIsNone(id_info_a.nick)
        self.assertTrue(id_info_a.is_private())
        self.assertFalse(IdentityInfo(db, id_a.public_identity()).is_private())

        # Test nick set/get
        id_info_a.nick = "me"
        self.assertEqual(id_info_a.nick, "me")
        id_info_a.nick = "you"
        self.assertEqual(id_info_a.nick, "you")
        id_info_a.nick = None
        self.assertIsNone(id_info_a.nick)

        # Test bad input
        self.assertRaises(TypeError, id_info_a.nick, 0)
        self.assertRaises(TypeError, id_info_a.nick, b'')
 def test_client_server_transaction(self):
     """Tests the whole, client driven transaction protocol and logic""" 
     
     client_db = ContentDB()
     server_db = ContentDB()
     server_db.add_messages([Message('fubar'), Message('foo'), Message('bar')])
 
     self.assertEqual(client_db.message_count, 0)
     self.assertEqual(server_db.message_count, 3)
 
     with TestServerHelper() as server_helper, TestClientHelper() as client_helper:
             
         client_transaction = ClientTransaction(client_helper.sock, client_db)
         server_transaction = ServerTransaction(server_helper.sock, server_db)
         
         """Run the client transactions asynchronously"""
         server_thread = threading.Thread(target=server_transaction.process)
         client_thread = threading.Thread(target=client_transaction.process)
         server_thread.start()
         client_thread.start()
         
         """Wait for client to hang up"""
         client_thread.join(1) # One sec should be plenty
         server_thread.join(2*TIMEOUT)
         
     """Make sure the client has updated the db"""
     self.assertEqual(client_db.message_count, 3)
     self.assertEqual(server_db.message_count, 3)
     self.assertEqual(len([srvmsg for srvmsg in server_db.get_messages() if srvmsg not in client_db.get_messages()]), 0) 
Beispiel #4
0
    def test_basic_client_transaction(self):
        """Tests the client transaction protocol and logic"""

        client_db = ContentDB()
        srv_db = ContentDB()
        tc = srv_db.add_messages(
            [Message('fubar'),
             Message('foo'), Message('bar')])

        self.assertEqual(client_db.message_count, 0)
        self.assertEqual(srv_db.message_count, 3)

        with TestServerHelper() as server_helper, TestClientHelper(
        ) as client_helper:

            client_transaction = ClientTransaction(client_helper.sock,
                                                   client_db)
            srv_sock = SocketTransaction(server_helper.sock, b'\n')
            """Run the client transaction in a separate thread"""
            thread = threading.Thread(target=client_transaction.process)
            thread.start()
            """Send a greeting (should be req. by client)"""
            srv_sock._write(
                Protocol.create_greeting_message(srv_db.id).encode())
            """Reading msg id list request"""
            rcv = srv_sock._read()
            self.assertEqual(
                rcv,
                Protocol.create_message_id_list_request().encode())
            """Sending the msg id list"""
            srv_sock._write(
                Protocol.create_message_id_list(
                    tc, srv_db.get_messages()).encode())
            """Reading msg list request"""
            rcv = srv_sock._read()
            self.assertEqual(
                rcv,
                Protocol.create_message_list_request(
                    [msg.id for msg in srv_db.get_messages()]).encode())
            """Sending the msg id list"""
            srv_sock._write(
                Protocol.create_message_list(srv_db.get_messages()).encode())
            """Wait for client to hang up"""
            thread.join(2 * TIMEOUT)
        """Make sure the client has updated the db"""
        self.assertEqual(client_db.message_count, 3)
        self.assertEqual(srv_db.message_count, 3)
        self.assertEqual(
            len([
                srvmsg for srvmsg in srv_db.get_messages()
                if srvmsg not in client_db.get_messages()
            ]), 0)
Beispiel #5
0
    def test_client_server_transaction(self):
        """Tests the whole, client driven transaction protocol and logic"""

        client_db = ContentDB()
        server_db = ContentDB()
        server_db.add_messages(
            [Message('fubar'),
             Message('foo'), Message('bar')])

        self.assertEqual(client_db.message_count, 0)
        self.assertEqual(server_db.message_count, 3)

        with TestServerHelper() as server_helper, TestClientHelper(
        ) as client_helper:

            client_transaction = ClientTransaction(client_helper.sock,
                                                   client_db)
            server_transaction = ServerTransaction(server_helper.sock,
                                                   server_db)
            """Run the client transactions asynchronously"""
            server_thread = threading.Thread(target=server_transaction.process)
            client_thread = threading.Thread(target=client_transaction.process)
            server_thread.start()
            client_thread.start()
            """Wait for client to hang up"""
            client_thread.join(1)  # One sec should be plenty
            server_thread.join(2 * TIMEOUT)
        """Make sure the client has updated the db"""
        self.assertEqual(client_db.message_count, 3)
        self.assertEqual(server_db.message_count, 3)
        self.assertEqual(
            len([
                srvmsg for srvmsg in server_db.get_messages()
                if srvmsg not in client_db.get_messages()
            ]), 0)
    def test_get_messages(self):
        """Test message retrieval."""

        db = ContentDB(tempfile.NamedTemporaryFile().name)

        _, mlist = db.get_messages()
        self.assertEqual(mlist, [])

        id1 = dandelion.identity.generate()
        id2 = dandelion.identity.generate()
        m1 = Message('M1')
        m2 = Message('M2')
        m3 = dandelion.message.create('M3', 1337, id1, id2)

        db.add_identities([id1])
        db.add_messages([m1, m2, m3])

        _, mlist = db.get_messages()
        self.assertTrue(m1 in mlist)
        self.assertTrue(m2 in mlist)
        self.assertTrue(m3 in mlist)

        _, mlist = db.get_messages([m1.id, m3.id])
        self.assertTrue(m1 in mlist)
        self.assertFalse(m2 in mlist)
        self.assertTrue(m3 in mlist)
    def test_single_message_interface(self):
        """Test functions relating to storing and recovering single messages"""
        
        db = ContentDB()
        
        first_msg = Message("A message")

        # Try to add junk
        self.assertRaises(ValueError, db.add_messages, None)
        self.assertRaises(TypeError, db.add_messages, 23)
        self.assertRaises(TypeError, db.add_messages, [None])

        # Add a single message        
        db.add_messages([first_msg])
        self.assertEqual(db.message_count, 1)
        self.assertEqual(db.contains_messages([first_msg]), [True])
    def __init__(self, config_file='dandelion.conf'):
        self._cfg_file_name = config_file
        self._server_config = ServerConfig()
        self._synchronizer_config = SynchronizerConfig()
        self._discoverer_config = DiscovererConfig()
        self._id_manager_config = IdentityConfig()
        self._ui_config = UiConfig()

        self.read_file()

        self._content_db = ContentDB(self._server_config.db_file)

        if self._id_manager_config.my_id is not None and not self._content_db.contains_identity(decode_b64_bytes(self._id_manager_config.my_id.encode())) :
            print("WARNING! Bad or non existing ID requested in config. Requested:", self._id_manager_config.my_id)
            self._id_manager_config.my_id = None

        if self._id_manager_config.my_id is not None:
            fp = decode_b64_bytes(self._id_manager_config.my_id.encode())
            try:
                self._identity = self._content_db.get_private_identity(fp)
                print("My claimed ID:", self._id_manager_config.my_id)
                return
            except ValueError:
                pass
            
        self._identity = dandelion.identity.generate()
        self._content_db.add_private_identity(self._identity)
        id_str = encode_b64_bytes(self._identity.fingerprint).decode()
        self._id_manager_config.my_id = id_str
    def test_get_identities(self):
        """Test identity retrieval."""

        db = ContentDB(tempfile.NamedTemporaryFile().name)

        id1 = dandelion.identity.generate()
        id2 = dandelion.identity.generate().public_identity()
        id3 = dandelion.identity.generate()

        db.add_identities([id1, id2, id3])
        db.add_messages([Message("fu")])

        _, idlist = db.get_identities()
        self.assertTrue(id1 in idlist)
        self.assertTrue(id2 in idlist)
        self.assertTrue(id3 in idlist)
        for id in idlist:
            self.assertFalse(id.rsa_key.is_private)
            self.assertFalse(id.dsa_key.is_private)

        _, idlist = db.get_identities(fingerprints=[id1.fingerprint, id2.fingerprint])
        self.assertTrue(id1 in idlist)
        self.assertTrue(id2 in idlist)
        self.assertFalse(id3 in idlist)
        for id in idlist:
            self.assertFalse(id.rsa_key.is_private)
            self.assertFalse(id.dsa_key.is_private)
    def test_singleton(self):
        """Test the singleton register / unregister function."""
        self.assertEqual(ContentDB.db, None)
        self.assertRaises(ContentDBException, ContentDB.register, None)
        self.assertRaises(ContentDBException, ContentDB.register, 23)
        self.assertRaises(ContentDBException, ContentDB.unregister)

        db = ContentDB(":memory:")
        ContentDB.register(db)
        self.assertRaises(ContentDBException, ContentDB.register, db)
        self.assertRaises(ContentDBException, ContentDB.register, ContentDB(":memory:"))

        db_back = ContentDB.db
        self.assertNotEqual(db_back, None)
        self.assertEqual(db_back, db)

        ContentDB.unregister()
        self.assertEqual(ContentDB.db, None)
    def test_client_server_transaction(self):
        """Tests the whole, client driven transaction protocol and logic"""

        client_db = ContentDB(tempfile.NamedTemporaryFile().name)
        server_db = ContentDB(tempfile.NamedTemporaryFile().name)

        id1 = dandelion.identity.generate()
        id2 = dandelion.identity.generate()
        server_db.add_identities([id1, id2])
        server_db.add_messages([Message("fubar"), dandelion.message.create("foo", None, id1, id2), Message("bar")])

        self.assertEqual(client_db.message_count, 0)
        self.assertEqual(client_db.identity_count, 0)
        self.assertEqual(server_db.message_count, 3)
        self.assertEqual(server_db.identity_count, 2)

        with TestServerHelper() as server_helper, TestClientHelper() as client_helper:

            client_transaction = ClientTransaction(client_helper.sock, client_db)
            server_transaction = ServerTransaction(server_helper.sock, server_db)

            """Run the client transactions asynchronously"""
            server_thread = threading.Thread(target=server_transaction.process)
            client_thread = threading.Thread(target=client_transaction.process)
            server_thread.start()
            client_thread.start()

            """Wait for client to hang up"""
            client_thread.join(1)  # One sec should be plenty
            server_thread.join(2 * TIMEOUT)

        """Make sure the client has updated the db"""
        self.assertEqual(client_db.message_count, 3)
        self.assertEqual(server_db.message_count, 3)
        self.assertEqual(client_db.identity_count, 2)
        self.assertEqual(server_db.identity_count, 2)

        self.assertEqual(
            len([srvmsg for srvmsg in server_db.get_messages()[1] if srvmsg not in client_db.get_messages()[1]]), 0
        )
        self.assertEqual(
            len([srvid for srvid in server_db.get_identities()[1] if srvid not in client_db.get_identities()[1]]), 0
        )
    def test_get_messages(self):
        """Test the message retrieval from msg id list"""
        
        db = ContentDB()

        m1 = Message('M1')
        m2 = Message('M2')
        m3 = Message('M3')
        
        db.add_messages([m1, m2, m3])
        
        mlist = db.get_messages()
        self.assertTrue(m1 in mlist)
        self.assertTrue(m2 in mlist)
        self.assertTrue(m3 in mlist)
        
        mlist = db.get_messages([m1.id, m3.id])
        self.assertTrue(m1 in mlist)
        self.assertFalse(m2 in mlist)
        self.assertTrue(m3 in mlist)
    def test_do_sync(self):
        cm = dandelion.config.ConfigManager(self.TEST_FILE)
        remote_db = ContentDB(tempfile.NamedTemporaryFile().name)
        local_db = ContentDB(tempfile.NamedTemporaryFile().name)
        d = dandelion.discoverer.Discoverer(cm.discoverer_config, cm.server_config)
        d.start()
        s = dandelion.synchronizer.Synchronizer(d, cm, local_db)
        s.start()

        # Start the "remote" server
        sc = ServerConfig()
        sc.ip = "127.0.0.1"
        sc.port = 12345
        server = Server(sc, remote_db, None)
        server.start()

        # Adding the node to the discoverer should prompt it to start synchronizing.
        d.add_node("127.0.0.1", 12345, pin=True)

        msg = local_db.get_messages()
        self.assertEqual(len(msg[1]), 0)

        remote_db.add_messages([Message("fubar")])

        # Need to wait for the sync to complete...
        time.sleep(5)

        # Complete sync, so we have the message locally
        msg = local_db.get_messages()
        self.assertEqual(len(msg[1]), 1)

        # Cleanup
        s.stop()
        d.stop()
        server.stop()
    def test_sqlite(self):
        """Perform some SQLite specific tests."""
        tmp = tempfile.NamedTemporaryFile()
        sqlitedb = ContentDB(tmp.name)

        self.assertTrue(len(sqlitedb.id), ContentDB._DBID_LENGTH_BYTES)
        self.assertTrue(ContentDB._TCID_LENGTH_BYTES > 1)
        self.assertTrue(isinstance(sqlitedb.id, bytes))
        self.assertEqual(sqlitedb.message_count, 0)

        m1 = Message('a')
        tc1 = sqlitedb.add_messages([m1, Message('b')])
        self.assertEqual(sqlitedb.message_count, 2)

        sqlitedb2 = ContentDB(tmp.name, sqlitedb.id) # New db is the same as old
        self.assertEqual(sqlitedb.id, sqlitedb2.id)
        self.assertEqual(sqlitedb.message_count, 2)

        tc2 = sqlitedb2.add_messages([Message('c')])
        self.assertEqual(sqlitedb.message_count, 3)
        self.assertEqual(sqlitedb2.message_count, 3)
        self.assertNotEqual(tc1, tc2)
    def test_basic_server_transaction(self):
        """Tests the server transaction protocol and logic"""

        db = ContentDB(tempfile.NamedTemporaryFile().name)
        db.add_identities([dandelion.identity.generate(), dandelion.identity.generate()])
        tc = db.add_messages([Message("fubar"), Message("foo"), Message("bar")])

        with TestServerHelper() as server_helper, TestClientHelper() as client_helper:
            srv_transaction = ServerTransaction(server_helper.sock, db)
            test_client = SocketTransaction(client_helper.sock, b"\n")

            """Run the server transaction in a separate thread to allow client access"""
            thread = threading.Thread(target=srv_transaction.process)
            thread.start()

            """Check greeting from server"""
            rcv = test_client._read()
            self.assertEqual(rcv, dandelion.protocol.create_greeting_message(db.id).encode())

            """Check response to mdgid list req"""
            test_client._write(dandelion.protocol.create_message_id_list_request(tc).encode())
            rcv = test_client._read()
            self.assertEqual(rcv, dandelion.protocol.create_message_id_list(tc, None).encode())

            """Check response to identityid list req"""
            test_client._write(dandelion.protocol.create_identity_id_list_request(tc).encode())
            rcv = test_client._read()
            self.assertEqual(rcv, dandelion.protocol.create_identity_id_list(tc, None).encode())

            """Check response to mdg req"""
            test_client._write(
                dandelion.protocol.create_message_list_request([msg.id for msg in db.get_messages()[1]]).encode()
            )
            rcv = test_client._read()
            self.assertEqual(rcv, dandelion.protocol.create_message_list(db.get_messages()[1]).encode())

            """Check response to identity req"""
            test_client._write(
                dandelion.protocol.create_identity_list_request(
                    [id.fingerprint for id in db.get_identities()[1]]
                ).encode()
            )
            rcv = test_client._read()
            self.assertEqual(rcv, dandelion.protocol.create_identity_list(db.get_identities()[1]).encode())

            """Wait for server (will time out if no requests)"""
            thread.join(2 * TIMEOUT)
Beispiel #16
0
    def test_basic_server_transaction(self):
        """Tests the server transaction protocol and logic"""

        db = ContentDB()
        tc = db.add_messages(
            [Message('fubar'),
             Message('foo'), Message('bar')])

        with TestServerHelper() as server_helper, TestClientHelper(
        ) as client_helper:
            srv_transaction = ServerTransaction(server_helper.sock, db)
            test_client = SocketTransaction(client_helper.sock, b'\n')
            """Run the server transaction in a separate thread to allow client access"""
            thread = threading.Thread(target=srv_transaction.process)
            thread.start()
            """Check greeting from server"""
            rcv = test_client._read()
            self.assertEqual(rcv,
                             Protocol.create_greeting_message(db.id).encode())
            """Check response to mdgid list req"""
            test_client._write(
                Protocol.create_message_id_list_request(tc).encode())
            rcv = test_client._read()
            self.assertEqual(
                rcv,
                Protocol.create_message_id_list(tc, None).encode())
            """Check response to mdg req"""
            test_client._write(
                Protocol.create_message_list_request(
                    [msg.id for msg in db.get_messages()]).encode())
            rcv = test_client._read()
            self.assertEqual(
                rcv,
                Protocol.create_message_list(db.get_messages()).encode())
            """Wait for server (will time out if no requests)"""
            thread.join(2 * TIMEOUT)
    def __init__(self, config_file=None):

        if config_file is None:
            self._cfg_file_name = 'dandelion.conf'
        else:
            self._cfg_file_name = config_file

        self._server_config = ServerConfig()
        self._synchronizer_config = SynchronizerConfig()
        self._id_manager_config = IdentityConfig()
        self._ui_config = UiConfig()

        self.read_file()

        self._content_db = ContentDB()
Beispiel #18
0
    def test_client_transaction_protocol_violation(self):
        """Tests the client transaction protocol and logic"""

        client_db = ContentDB()

        with TestServerHelper() as server_helper, TestClientHelper(
        ) as client_helper:

            client_transaction = ClientTransaction(client_helper.sock,
                                                   client_db)
            srv_sock = SocketTransaction(server_helper.sock, b'\n')
            """Run the client transaction in a separate thread"""
            thread = threading.Thread(target=client_transaction.process)
            thread.start()
            """Send a greeting (should be req. by client)"""
            srv_sock._write(b'NON PROTOCOL MESSAGE\n')
            self.assertRaises(socket.timeout, srv_sock._read)
            """Wait for client to hang up"""
            thread.join(2 * TIMEOUT)
Beispiel #19
0
    def test_server_transaction_protocol_violation(self):
        """Tests the servers response to an invalid request"""

        db = ContentDB()

        with TestServerHelper() as server_helper, TestClientHelper(
        ) as client_helper:
            srv_transaction = ServerTransaction(server_helper.sock, db)
            test_client = SocketTransaction(client_helper.sock, b'\n')
            """Run the server transaction in a separate thread to allow client access"""
            thread = threading.Thread(target=srv_transaction.process)
            thread.start()
            """Check greeting from server"""
            rcv = test_client._read()
            self.assertEqual(rcv,
                             Protocol.create_greeting_message(db.id).encode())
            """Check response to mdgid list req"""
            test_client._write(b'NON PROTOCOL MESSAGE\n')
            self.assertRaises(socket.timeout, test_client._read)
            """Wait for server (will time out if no requests)"""
            thread.join(2 * TIMEOUT)
            server_helper, client_helper = None, None
Beispiel #20
0
    def __init__(self, config_file=None):

        self._cfg = self.CONFIG_DEFAULTS.copy()

        if not config_file:
            self._config_file = self.DEFAULT_CONFIG_FILE
        else:
            self._config_file = config_file

        if not self._config_file_exists():
            self.write_defaults_to_config_file()

        self.load_config()

        self._content_db = ContentDB()

        # store all dict values as attributes so we can access the like this
        # self.server_time (the same as self_cfg['synchronization']['server_time']
        # one downfall is that we cant have settings with the same name even though they are
        # in different sections.
        for key in self._cfg:
            setattr(self, key, self._cfg[key])
            for k, v in self._cfg[key].items():
                setattr(self.__class__, k, v)
    def test_basic_client_transaction(self):
        """Tests the client transaction protocol and logic""" 
        
        client_db = ContentDB()
        srv_db = ContentDB()
        tc = srv_db.add_messages([Message('fubar'), Message('foo'), Message('bar')])
    
        self.assertEqual(client_db.message_count, 0)
        self.assertEqual(srv_db.message_count, 3)
    
        with TestServerHelper() as server_helper, TestClientHelper() as client_helper:
            
            client_transaction = ClientTransaction(client_helper.sock, client_db)
            srv_sock = SocketTransaction(server_helper.sock, b'\n')
            
            """Run the client transaction in a separate thread"""
            thread = threading.Thread(target=client_transaction.process)
            thread.start()
            
            """Send a greeting (should be req. by client)"""
            srv_sock._write(Protocol.create_greeting_message(srv_db.id).encode())
            
            """Reading msg id list request"""
            rcv = srv_sock._read()
            self.assertEqual(rcv, Protocol.create_message_id_list_request().encode())

            """Sending the msg id list"""
            srv_sock._write(Protocol.create_message_id_list(tc, srv_db.get_messages()).encode())

            """Reading msg list request"""
            rcv = srv_sock._read()
            self.assertEqual(rcv, Protocol.create_message_list_request([msg.id for msg in srv_db.get_messages()]).encode())

            """Sending the msg id list"""
            srv_sock._write(Protocol.create_message_list(srv_db.get_messages()).encode())

            """Wait for client to hang up"""
            thread.join(2*TIMEOUT)
                
        """Make sure the client has updated the db"""
        self.assertEqual(client_db.message_count, 3)
        self.assertEqual(srv_db.message_count, 3)
        self.assertEqual(len([srvmsg for srvmsg in srv_db.get_messages() if srvmsg not in client_db.get_messages()]), 0) 
    def test_time_cookies(self):
        """Test the data base time cookies (revision) functionality""" 
        
        db = ContentDB()

        # Adding a message        
        first_msg = Message('A Single Message')
        first_cookie = db.add_messages([first_msg])
        self.assertNotEqual(first_cookie, None)

        # Same message again
        self.assertEqual(first_cookie, db.add_messages([first_msg]))

        # New message, new cookie
        second_msg = Message('Another Single Message')
        second_cookie = db.add_messages([second_msg])
        self.assertNotEqual(second_cookie, None)
        self.assertNotEqual(second_cookie, first_cookie)

        # Since first should only be second
        tc, some_messages = db.messages_since(first_cookie)
        self.assertNotEqual(some_messages, None)
        self.assertEqual(tc, second_cookie)

        self.assertEqual(len(some_messages), 1)
        self.assertEqual(some_messages[0], second_msg)
        
        # Nothing new since last message was added
        tc, last_messages = db.messages_since(second_cookie)
        self.assertNotEqual(last_messages, None)
        self.assertEqual(len(last_messages), 0)
        self.assertEqual(tc, second_cookie)
        
        # Trying some bad input
        self.assertRaises(TypeError, db.messages_since, 0)
        self.assertRaises(TypeError, db.messages_since, '')
        self.assertRaises(TypeError, db.messages_since, 'fubar')
        self.assertRaises(ValueError, db.messages_since, b'')
        self.assertRaises(ValueError, db.messages_since, b'1337')
    def test_basic_client_transaction(self):
        """Tests the client transaction protocol and logic"""

        client_db = ContentDB(tempfile.NamedTemporaryFile().name)
        srv_db = ContentDB(tempfile.NamedTemporaryFile().name)

        self.assertEqual(client_db.message_count, 0)
        srv_db.add_identities([dandelion.identity.generate(), dandelion.identity.generate()])
        tc = srv_db.add_messages([Message("fubar"), Message("foo"), Message("bar")])

        self.assertEqual(client_db.message_count, 0)
        self.assertEqual(client_db.identity_count, 0)
        self.assertEqual(srv_db.message_count, 3)
        self.assertEqual(srv_db.identity_count, 2)

        with TestServerHelper() as server_helper, TestClientHelper() as client_helper:

            client_transaction = ClientTransaction(client_helper.sock, client_db)
            srv_sock = SocketTransaction(server_helper.sock, b"\n")

            """Run the client transaction in a separate thread"""
            thread = threading.Thread(target=client_transaction.process)
            thread.start()
            """Send a greeting (should be req. by client)"""
            srv_sock._write(dandelion.protocol.create_greeting_message(srv_db.id).encode())

            """Reading msg id list request"""
            rcv = srv_sock._read()
            self.assertEqual(rcv, dandelion.protocol.create_message_id_list_request().encode())

            """Sending the msg id list"""
            srv_sock._write(dandelion.protocol.create_message_id_list(tc, srv_db.get_messages()[1]).encode())

            """Reading msg list request"""
            rcv = srv_sock._read()
            expected_msgs = (
                dandelion.protocol.create_message_list_request([msg.id for msg in srv_db.get_messages()[1]])
                .split(" ")[1][:-1]
                .split(";")
            )
            for msg in expected_msgs:
                self.assertNotEqual(rcv.find(msg.encode()), -1)

            """Sending the msg id list"""
            srv_sock._write(dandelion.protocol.create_message_list(srv_db.get_messages()[1]).encode())

            """Reading identity id list request"""
            rcv = srv_sock._read()
            self.assertEqual(rcv, dandelion.protocol.create_identity_id_list_request().encode())

            """Sending the identity id list"""
            srv_sock._write(dandelion.protocol.create_identity_id_list(tc, srv_db.get_identities()[1]).encode())

            """Reading identity list request"""
            rcv = srv_sock._read()
            expected_ids = (
                dandelion.protocol.create_identity_list_request([id.fingerprint for id in srv_db.get_identities()[1]])
                .split(" ")[1][:-1]
                .split(";")
            )
            for id in expected_ids:
                self.assertNotEqual(rcv.find(id.encode()), -1)

            """Sending the msg id list"""
            srv_sock._write(dandelion.protocol.create_identity_list(srv_db.get_identities()[1]).encode())

            """Wait for client to hang up"""
            thread.join(2 * TIMEOUT)

        """Make sure the client has updated the db"""
        self.assertEqual(client_db.message_count, 3)
        self.assertEqual(srv_db.message_count, 3)
        self.assertEqual(
            len([srvmsg for srvmsg in srv_db.get_messages()[1] if srvmsg not in client_db.get_messages()[1]]), 0
        )
    def test_message_interface(self):
        """Test functions relating to storing and recovering messages."""

        db = ContentDB(tempfile.NamedTemporaryFile().name)

        id1 = dandelion.identity.generate()
        id2 = dandelion.identity.generate()
        first_msg_list = [Message('A'), Message('B'), Message('III', timestamp=3),
                          dandelion.message.create("W Sender", sender=id1),
                          dandelion.message.create("W Receiver", receiver=id2),
                          dandelion.message.create("W Sender And Receiver", sender=id1, receiver=id2)]

        # Try to add junk
        self.assertRaises(TypeError, db.add_messages, None)
        self.assertRaises(TypeError, db.add_messages, 23)
        self.assertRaises(AttributeError, db.add_messages, [None])

        # Add a message list        
        self.assertEqual(db.message_count, 0)
        db.add_messages(first_msg_list)
        self.assertNotEqual(db.message_count, None)
        self.assertEqual(db.message_count, len(first_msg_list))
        self.assertEqual([db.contains_message(m.id) for m in first_msg_list], [True, True, True, True, True, True])

        # And for another message list? 
        second_msg_list = [Message('C'), Message('A')]
        self.assertEqual([db.contains_message(m.id) for m in second_msg_list], [False, True])

        # Adding the second message list
        db.add_messages(second_msg_list)
        self.assertEqual(db.message_count, 7)
        self.assertEqual([db.contains_message(m.id) for m in first_msg_list], [True, True, True, True, True, True])
        self.assertEqual([db.contains_message(m.id) for m in second_msg_list], [True, True])

        # Remove a list
        db.remove_messages(first_msg_list)
        self.assertEqual(db.message_count, 1)
        self.assertEqual([db.contains_message(m.id) for m in first_msg_list], [False, False, False, False, False, False])
        self.assertEqual([db.contains_message(m.id) for m in second_msg_list], [True, False])

        # Remove same message list 
        db.remove_messages(first_msg_list)
        self.assertEqual(db.message_count, 1)
        self.assertEqual([db.contains_message(m.id) for m in first_msg_list], [False, False, False, False, False, False])
        self.assertEqual([db.contains_message(m.id) for m in second_msg_list], [True, False])

        # Remove all messages
        db.remove_messages()
        self.assertEqual(db.message_count, 0)
        self.assertEqual([db.contains_message(m.id) for m in first_msg_list], [False, False, False, False, False, False])
        self.assertEqual([db.contains_message(m.id) for m in second_msg_list], [False, False])
    def test_remote_cookies(self):
        """Test the remote time cookie interface"""
        db = ContentDB(tempfile.NamedTemporaryFile().name)

        remotefp_1 = b"1337"
        remotefp_2 = b"2342"
        remotetc_1 = b"1"
        remotetc_2 = b"2"

        # No time cookie for the db yet       
        self.assertIsNone(db.get_last_time_cookie(remotefp_1))

        # Initial tc
        db.update_last_time_cookie(remotefp_1, remotetc_1)
        self.assertEqual(db.get_last_time_cookie(remotefp_1), remotetc_1)

        # Same tc again
        db.update_last_time_cookie(remotefp_1, remotetc_1)
        self.assertEqual(db.get_last_time_cookie(remotefp_1), remotetc_1)

        # Second tc
        db.update_last_time_cookie(remotefp_1, remotetc_2)
        self.assertEqual(db.get_last_time_cookie(remotefp_1), remotetc_2)

        # Second db
        db.update_last_time_cookie(remotefp_2, remotetc_1)
        self.assertEqual(db.get_last_time_cookie(remotefp_1), remotetc_2)
        self.assertEqual(db.get_last_time_cookie(remotefp_2), remotetc_1)
    def test_list_message_interface(self):
        """Test functions relating to storing and recovering single messages"""
        
        db = ContentDB()
        
        first_msg_list = [Message('A'), Message('B')]

        # Add a message list        
        db.add_messages(first_msg_list)
        self.assertNotEqual(db.message_count, None)
        self.assertEqual(db.message_count, len(first_msg_list))
        self.assertEqual(db.contains_messages(first_msg_list), [True, True])

        # And for another message list? 
        second_msg_list = [Message('C'), Message('A')]
        self.assertEqual(db.contains_messages(second_msg_list), [False, True])
        
        # Adding the second message list
        db.add_messages(second_msg_list)
        self.assertEqual(db.message_count, 3)
        self.assertEqual(db.contains_messages(first_msg_list), [True, True])
        self.assertEqual(db.contains_messages(second_msg_list), [True, True])

        # Remove a list
        db.remove_messages(first_msg_list)
        self.assertEqual(db.message_count, 1)
        self.assertEqual(db.contains_messages(first_msg_list), [False, False])
        self.assertEqual(db.contains_messages(second_msg_list), [True, False])

        # Remove same message list 
        db.remove_messages(first_msg_list)
        self.assertEqual(db.message_count, 1)
        self.assertEqual(db.contains_messages(first_msg_list), [False, False])
        self.assertEqual(db.contains_messages(second_msg_list), [True, False])
        
        # Remove all messages
        db.remove_messages()
        self.assertEqual(db.message_count, 0)
        self.assertEqual(db.contains_messages(first_msg_list), [False, False])
        self.assertEqual(db.contains_messages(second_msg_list), [False, False])
Beispiel #27
0
class ConfigManager:

    def __init__(self, config_file='dandelion.conf'):
        self._cfg_file_name = config_file
        self._server_config = ServerConfig()
        self._synchronizer_config = SynchronizerConfig()
        self._discoverer_config = DiscovererConfig()
        self._id_manager_config = IdentityConfig()
        self._ui_config = UiConfig()

        self.read_file()

        self._content_db = ContentDB(self._server_config.db_file)

        if self._id_manager_config.my_id is not None and not self._content_db.contains_identity(decode_b64_bytes(self._id_manager_config.my_id.encode())) :
            print("WARNING! Bad or non existing ID requested in config. Requested:", self._id_manager_config.my_id)
            self._id_manager_config.my_id = None

        if self._id_manager_config.my_id is not None:
            fp = decode_b64_bytes(self._id_manager_config.my_id.encode())
            try:
                self._identity = self._content_db.get_private_identity(fp)
                print("My claimed ID:", self._id_manager_config.my_id)
                return
            except ValueError:
                pass
            
        self._identity = dandelion.identity.generate()
        self._content_db.add_private_identity(self._identity)
        id_str = encode_b64_bytes(self._identity.fingerprint).decode()
        self._id_manager_config.my_id = id_str

    @property
    def config_file(self):
        return self._cfg_file_name

    @property
    def server_config(self):
        return self._server_config

    @property
    def synchronizer_config(self):
        return self._synchronizer_config

    @property
    def discoverer_config(self):
        return self._discoverer_config

    @property
    def identity_manager_config(self):
        return self._id_manager_config

    @property
    def ui_config(self):
        return self._ui_config

    @property
    def content_db(self):
        return self._content_db

    @property
    def identity(self):
        return self._identity

    def write_file(self):

        confparser = configparser.ConfigParser()

        self._server_config.store(confparser)
        self._ui_config.store(confparser)
        self._id_manager_config.store(confparser)
        self._discoverer_config.store(confparser)

        with open(self._cfg_file_name, 'w') as configfile:
            confparser.write(configfile)

    def read_file(self):

        confparser = configparser.ConfigParser()
        confparser.read(self._cfg_file_name)

        self._server_config.load(confparser)
        self._ui_config.load(confparser)
        self._id_manager_config.load(confparser)
        self._discoverer_config.load(confparser)
    def test_identity_info_nick(self):
        """"Test getting and setting nickname"""

        db = ContentDB(tempfile.NamedTemporaryFile().name)
        id_a = dandelion.identity.generate()
        db.add_identities([id_a])

        # Check for empty nicks
        self.assertIsNone(db.get_nick(b'1337'))
        self.assertIsNone(db.get_nick(id_a.fingerprint))

        # Test setting a nick
        db.set_nick(id_a.fingerprint, "me")
        self.assertEqual(db.get_nick(id_a.fingerprint), "me")
        db.set_nick(id_a.fingerprint, "you")
        self.assertEqual(db.get_nick(id_a.fingerprint), "you")
        db.set_nick(id_a.fingerprint, None)
        self.assertIsNone(db.get_nick(id_a.fingerprint))

        # Trying some bad input
        self.assertRaises(TypeError, db.get_nick, 0)
        self.assertRaises(TypeError, db.get_nick, '')
        self.assertRaises(TypeError, db.get_nick, None)
        self.assertRaises(ValueError, db.get_nick, b'')

        self.assertRaises(TypeError, db.set_nick, id_a.fingerprint, 0)
        self.assertRaises(TypeError, db.set_nick, id_a.fingerprint, b'')
        self.assertRaises(TypeError, db.set_nick, None, "qwerty")
        self.assertRaises(TypeError, db.set_nick, 0, "qwerty")
        self.assertRaises(TypeError, db.set_nick, '', "qwerty")
        self.assertRaises(ValueError, db.set_nick, b'', "qwerty")
    def test_private_identities(self):
        """Test private id interface"""

        db = ContentDB(tempfile.NamedTemporaryFile().name)
        id_priv = dandelion.identity.generate()
        id_pub = dandelion.identity.generate().public_identity()

        # Add junk
        self.assertRaises(TypeError, db.add_private_identity, None)
        self.assertRaises(ValueError, db.add_private_identity, id_pub)

        # Add, get, remove
        db.add_private_identity(id_priv)
        id = db.get_private_identity(id_priv.fingerprint)

        self.assertEqual(id_priv.fingerprint, id.fingerprint)
        self.assertEqual(id_priv, id)
        self.assertTrue(IdentityInfo(db, id).is_private())

        db.remove_private_identity(id_priv, keep_public_identity=False)
        self.assertFalse(db.contains_identity(id_priv.fingerprint))

        # Add and remove private, but keep public
        db.add_private_identity(id_priv)
        db.remove_private_identity(id_priv, keep_public_identity=True)
        self.assertTrue(db.contains_identity(id_priv.fingerprint))
        self.assertFalse(IdentityInfo(db, db.get_identities([id_priv.fingerprint])[1][0]).is_private())
        self.assertRaises(ValueError, db.get_private_identity, id_priv.fingerprint)
    def test_time_cookies(self):
        """Test the data base time cookies (revision) functionality."""

        db = ContentDB(tempfile.NamedTemporaryFile().name)

        # Adding a message        
        first_msg = Message('A Single Message')
        first_cookie = db.add_messages([first_msg])
        self.assertNotEqual(first_cookie, None)
        self.assertTrue(isinstance(first_cookie, bytes))
        self.assertTrue((db.get_last_time_cookie(None) is None) or (db.get_last_time_cookie(None) == first_cookie))

        # Same message again
        self.assertEqual(first_cookie, db.add_messages([first_msg]))

        # New message, new cookie
        id1 = dandelion.identity.generate()
        id2 = dandelion.identity.generate()
        second_msg = dandelion.message.create('Another Single Message', sender=id1, receiver=id2)
        second_cookie = db.add_messages([second_msg])
        self.assertNotEqual(second_cookie, None)
        self.assertNotEqual(second_cookie, first_cookie)
        self.assertTrue((db.get_last_time_cookie(None) is None) or (db.get_last_time_cookie(None) == second_cookie))

        # Since first should only be second
        tc, some_messages = db.get_messages(time_cookie=first_cookie)
        self.assertNotEqual(some_messages, None)
        self.assertEqual(tc, second_cookie)

        self.assertEqual(len(some_messages), 1)
        self.assertEqual(some_messages[0], second_msg)

        # Nothing new since last message was added
        tc, last_messages = db.get_messages(time_cookie=second_cookie)
        self.assertNotEqual(last_messages, None)
        self.assertEqual(len(last_messages), 0)
        self.assertEqual(tc, second_cookie)

        # Same id gives same tc
        self.assertEqual(second_cookie, db.add_messages([first_msg]))

        # New identity, new cookie
        identity = dandelion.identity.generate()
        third_cookie = db.add_identities([identity])
        self.assertNotEqual(third_cookie, None)
        self.assertNotEqual(third_cookie, second_cookie)
        self.assertTrue(db.get_last_time_cookie() == third_cookie)

        # Trying some bad input
        self.assertRaises(TypeError, db.get_messages, [], 0)
        self.assertRaises(TypeError, db.get_messages, [], '')
        self.assertRaises(TypeError, db.get_messages, [], 'fubar')
        self.assertRaises(ValueError, db.get_messages, [], b'')
        self.assertRaises(ValueError, db.get_messages, [], b'1337')
    def test_identity_interface(self):
        """Test functions relating to storing and recovering identities."""

        db = ContentDB(tempfile.NamedTemporaryFile().name)

        _, idlist = db.get_identities()
        self.assertEqual(idlist, [])


        id_a = dandelion.identity.generate()
        id_b = dandelion.identity.generate()
        first_id_list = [id_a, id_b]

        # Try to add junk
        self.assertRaises(TypeError, db.add_identities, None)
        self.assertRaises(TypeError, db.add_identities, 23)
        self.assertRaises(AttributeError, db.add_identities, [None])

        # Add a message list
        self.assertEqual(db.identity_count, 0)
        db.add_identities(first_id_list)
        self.assertNotEqual(db.identity_count, None)
        self.assertEqual(db.identity_count, len(first_id_list))
        self.assertEqual([db.contains_identity(id.fingerprint) for id in first_id_list], [True, True])

        # And for another message list? 
        second_id_list = [dandelion.identity.generate(), id_a]
        self.assertEqual([db.contains_identity(id.fingerprint) for id in second_id_list], [False, True])

        # Adding the second message list
        db.add_identities(second_id_list)
        self.assertEqual(db.identity_count, 3)
        self.assertEqual([db.contains_identity(id.fingerprint) for id in first_id_list], [True, True])
        self.assertEqual([db.contains_identity(id.fingerprint) for id in second_id_list], [True, True])

        # Remove a list
        db.remove_identities(first_id_list)
        self.assertEqual(db.identity_count, 1)
        self.assertEqual([db.contains_identity(id.fingerprint) for id in first_id_list], [False, False])
        self.assertEqual([db.contains_identity(id.fingerprint) for id in second_id_list], [True, False])

        # Remove same message list 
        db.remove_identities(first_id_list)
        self.assertEqual(db.identity_count, 1)
        self.assertEqual([db.contains_identity(id.fingerprint) for id in first_id_list], [False, False])
        self.assertEqual([db.contains_identity(id.fingerprint) for id in second_id_list], [True, False])

        # Remove all messages
        db.remove_identities()
        self.assertEqual(db.identity_count, 0)
        self.assertEqual([db.contains_identity(id.fingerprint) for id in first_id_list], [False, False])
        self.assertEqual([db.contains_identity(id.fingerprint) for id in second_id_list], [False, False])