aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/odhtdb/Database.hpp24
-rw-r--r--include/odhtdb/DatabaseStorage.hpp9
-rw-r--r--src/Database.cpp36
-rw-r--r--src/DatabaseStorage.cpp24
4 files changed, 88 insertions, 5 deletions
diff --git a/include/odhtdb/Database.hpp b/include/odhtdb/Database.hpp
index e78bc6e..ecdf70c 100644
--- a/include/odhtdb/Database.hpp
+++ b/include/odhtdb/Database.hpp
@@ -125,6 +125,24 @@ namespace odhtdb
std::shared_ptr<OwnedMemory> key;
std::shared_ptr<Hash> hash;
};
+
+ struct DatabaseSeedInfo
+ {
+ std::shared_ptr<std::future<size_t>> newDataListenerFuture;
+ std::shared_ptr<std::future<size_t>> responseKeyFuture;
+ std::shared_ptr<std::future<size_t>> requestOldDataListenerFuture;
+
+ std::shared_ptr<dht::InfoHash> reponseKeyInfoHash;
+
+ DatabaseSeedInfo(){}
+ DatabaseSeedInfo(const DatabaseSeedInfo &other)
+ {
+ newDataListenerFuture = other.newDataListenerFuture;
+ responseKeyFuture = other.responseKeyFuture;
+ requestOldDataListenerFuture = other.requestOldDataListenerFuture;
+ reponseKeyInfoHash = other.reponseKeyInfoHash;
+ }
+ };
class Database
{
@@ -133,13 +151,16 @@ namespace odhtdb
Database(const char *bootstrapNodeAddr, u16 port, const boost::filesystem::path &storageDir);
~Database();
+ // Safe to call multiple times with same node hash, will be ignored if the node is already beeing seeded
void seed(const DatabaseNode &nodeToSeed);
+ void stopSeeding(const Hash &nodeHash);
+
// Throws DatabaseCreateException on failure.
std::unique_ptr<DatabaseCreateResponse> create(const std::string &ownerName, const std::string &nodeName);
// Throws DatabaseCreateException on failure.
std::unique_ptr<DatabaseCreateResponse> create(const std::string &ownerName, const Signature::KeyPair &keyPair, const std::string &nodeName);
// Throws PermissionDeniedException if user @userToPerformActionWith is not allowed to add data to node
- void addData(const DatabaseNode &nodeInfo, LocalUser *userToPerformActionWith, DataView dataToAdd);
+ void addData(const DatabaseNode &nodeInfo, const LocalUser *userToPerformActionWith, DataView dataToAdd);
// Throws PermissionDeniedException if user @userToPerformActionWith is not allowed to add user @userToAdd to group @groupToAddUserTo
void addUser(const DatabaseNode &nodeInfo, LocalUser *userToPerformActionWith, const std::string &userToAddName, const Signature::PublicKey &userToAddPublicKey, Group *groupToAddUserTo);
void commit();
@@ -167,5 +188,6 @@ namespace odhtdb
std::function<void(const DatabaseCreateNodeRequest&)> onCreateNodeCallbackFunc;
std::function<void(const DatabaseAddNodeRequest&)> onAddNodeCallbackFunc;
std::function<void(const DatabaseAddUserRequest&)> onAddUserCallbackFunc;
+ MapHash<DatabaseSeedInfo> seedInfoMap;
};
}
diff --git a/include/odhtdb/DatabaseStorage.hpp b/include/odhtdb/DatabaseStorage.hpp
index 85a61eb..9cfe12d 100644
--- a/include/odhtdb/DatabaseStorage.hpp
+++ b/include/odhtdb/DatabaseStorage.hpp
@@ -140,9 +140,15 @@ namespace odhtdb
// Returns nullptr if no storage with provided hash exists
const DatabaseStorageObjectList* getStorage(const Hash &hash) const;
+ // Returns nullptr if node @nodeHash doesn't exist
+ const DataViewMap<Group*>* getNodeGroups(const Hash &nodeHash);
+
// Returns nullptr if a group with id @groupId doesn't exist in node @nodeHash or if no node with id @nodeHash exists
Group* getGroupById(const Hash &nodeHash, uint8_t groupId[GROUP_ID_LENGTH]) const;
+ // Returns nullptr if node @nodeHash doesn't exist
+ const Signature::MapPublicKey<User*>* getNodeUsers(const Hash &nodeHash);
+
// Returns nullptr if a user with public key @publicKey doesn't exist in node @nodeHash or if no node with id @nodeHash exists
User* getUserByPublicKey(const Hash &nodeHash, const Signature::PublicKey &userPublicKey) const;
@@ -159,6 +165,9 @@ namespace odhtdb
// Safe to call multiple times.
std::vector<NodeLocalUser> getLocalNodeUsers(const Signature::KeyPair &keyPair);
+ // Returns true and node decryption key if node exists and we have the decryption key,
+ // otherwise return false and OwnedMemory with data set to nullptr
+ std::pair<bool, std::shared_ptr<OwnedMemory>> getNodeDecryptionKey(const Hash &nodeHash);
void setNodeDecryptionKey(const Hash &nodeHash, const DataView &decryptionKey);
const dht::crypto::Identity& getIdentity() const;
diff --git a/src/Database.cpp b/src/Database.cpp
index 6f864b4..7281025 100644
--- a/src/Database.cpp
+++ b/src/Database.cpp
@@ -140,6 +140,14 @@ namespace odhtdb
void Database::seed(const DatabaseNode &nodeToSeed)
{
+ if(seedInfoMap.find(*nodeToSeed.getRequestHash()) != seedInfoMap.end())
+ {
+ Log::warn("You are already seeding node %s, ignoring...", nodeToSeed.getRequestHash()->toString().c_str());
+ return;
+ }
+
+ DatabaseSeedInfo newSeedInfo;
+
// TODO: Use cached files and seed those. If none exists, request new files to seed.
// If nobody requests my cached files in a long time, request new files to seed and remove cached files
// (only if there are plenty of other seeders for the cached files. This could also cause race issue
@@ -150,7 +158,7 @@ namespace odhtdb
Log::debug("Seeding key: %s", nodeToSeed.getRequestHash()->toString().c_str());
DhtKey dhtKey(*nodeToSeed.getRequestHash());
- node.listen(dhtKey.getNewDataListenerKey(), [this, nodeToSeed](const shared_ptr<Value> &value)
+ auto newDataListenerFuture = node.listen(dhtKey.getNewDataListenerKey(), [this, nodeToSeed](const shared_ptr<Value> &value)
{
Log::debug("Seed: New data listener received data...");
const Hash requestHash(value->data.data(), value->data.size());
@@ -160,12 +168,14 @@ namespace odhtdb
else
return listenAddData(value, requestHash, nodeToSeed.getRequestHash(), nodeToSeed.getNodeEncryptionKey());
});
+ newSeedInfo.newDataListenerFuture = make_shared<future<size_t>>(move(newDataListenerFuture));
u8 responseKey[OPENDHT_INFOHASH_LEN];
randombytes_buf(responseKey, OPENDHT_INFOHASH_LEN);
+ newSeedInfo.reponseKeyInfoHash = make_shared<InfoHash>(responseKey, OPENDHT_INFOHASH_LEN);
// TODO: If this response key is spammed, generate a new one.
- node.listen(InfoHash(responseKey, OPENDHT_INFOHASH_LEN), [this, nodeToSeed](const shared_ptr<Value> &value)
+ auto responseKeyFuture = node.listen(*newSeedInfo.reponseKeyInfoHash, [this, nodeToSeed](const shared_ptr<Value> &value)
{
const Hash requestHash(value->data.data(), value->data.size());
if(requestHash == *nodeToSeed.getRequestHash())
@@ -173,10 +183,11 @@ namespace odhtdb
else
return listenAddData(value, requestHash, nodeToSeed.getRequestHash(), nodeToSeed.getNodeEncryptionKey());
});
+ newSeedInfo.responseKeyFuture = make_shared<future<size_t>>(move(responseKeyFuture));
// TODO: Before listening on this key, we should check how many remote peers are also providing this data.
// This is to prevent too many peers from responding to a request to get old data.
- node.listen(dhtKey.getRequestOldDataKey(), [this, nodeToSeed](const shared_ptr<Value> &value)
+ auto requestOldDataListenerFuture = node.listen(dhtKey.getRequestOldDataKey(), [this, nodeToSeed](const shared_ptr<Value> &value)
{
Log::debug("Request: Got request to send old data");
try
@@ -220,6 +231,9 @@ namespace odhtdb
}
return true;
});
+ newSeedInfo.requestOldDataListenerFuture = make_shared<future<size_t>>(move(requestOldDataListenerFuture));
+
+ seedInfoMap[*nodeToSeed.getRequestHash()] = newSeedInfo;
sibs::SafeSerializer serializer;
serializer.add((u64)0); // Timestamp in microseconds, fetch data newer than this. // TODO: Get timestamp from database storage
@@ -233,6 +247,20 @@ namespace odhtdb
//node.listen(CREATE_DATA_HASH, bind(&Database::listenCreateData, this, _1));
//node.listen(ADD_DATA_HASH, bind(&Database::listenAddData, this, _1));
}
+
+ void Database::stopSeeding(const Hash &nodeHash)
+ {
+ auto seedInfoIt = seedInfoMap.find(nodeHash);
+ if(seedInfoIt != seedInfoMap.end())
+ {
+ // TODO: Verify if doing get on listener future stalls program forever... Opendht documentation is not clear on this
+ DhtKey dhtKey(nodeHash);
+ node.cancelListen(dhtKey.getNewDataListenerKey(), seedInfoIt->second.newDataListenerFuture->get());
+ node.cancelListen(dhtKey.getRequestOldDataKey(), seedInfoIt->second.requestOldDataListenerFuture->get());
+ node.cancelListen(*seedInfoIt->second.reponseKeyInfoHash, seedInfoIt->second.responseKeyFuture->get());
+ seedInfoMap.erase(seedInfoIt);
+ }
+ }
unique_ptr<DatabaseCreateResponse> Database::create(const string &ownerName, const string &nodeName)
{
@@ -286,7 +314,7 @@ namespace odhtdb
}
}
- void Database::addData(const DatabaseNode &nodeInfo, LocalUser *userToPerformActionWith, DataView dataToAdd)
+ void Database::addData(const DatabaseNode &nodeInfo, const LocalUser *userToPerformActionWith, DataView dataToAdd)
{
if(!userToPerformActionWith->isAllowedToPerformAction(PermissionType::ADD_DATA))
{
diff --git a/src/DatabaseStorage.cpp b/src/DatabaseStorage.cpp
index 0e9fa32..384ef5f 100644
--- a/src/DatabaseStorage.cpp
+++ b/src/DatabaseStorage.cpp
@@ -692,6 +692,14 @@ namespace odhtdb
return nullptr;
}
+ const DataViewMap<Group*>* DatabaseStorage::getNodeGroups(const Hash &nodeHash)
+ {
+ auto groupByIdMapIt = nodeGroupByIdMap.find(nodeHash);
+ if(groupByIdMapIt != nodeGroupByIdMap.end())
+ return groupByIdMapIt->second;
+ return nullptr;
+ }
+
Group* DatabaseStorage::getGroupById(const Hash &nodeHash, uint8_t groupId[GROUP_ID_LENGTH]) const
{
auto groupByIdMapIt = nodeGroupByIdMap.find(nodeHash);
@@ -704,6 +712,14 @@ namespace odhtdb
return nullptr;
}
+ const Signature::MapPublicKey<User*>* DatabaseStorage::getNodeUsers(const Hash &nodeHash)
+ {
+ auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash);
+ if(publicKeyUserDataMapIt != nodePublicKeyUserDataMap.end())
+ return publicKeyUserDataMapIt->second;
+ return nullptr;
+ }
+
User* DatabaseStorage::getUserByPublicKey(const Hash &nodeHash, const Signature::PublicKey &userPublicKey) const
{
auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash);
@@ -806,6 +822,14 @@ namespace odhtdb
return localUsers;
}
+ std::pair<bool, std::shared_ptr<OwnedMemory>> DatabaseStorage::getNodeDecryptionKey(const Hash &nodeHash)
+ {
+ auto nodeDecryptionKeyIt = nodeDecryptionKeyMap.find(nodeHash);
+ if(nodeDecryptionKeyIt != nodeDecryptionKeyMap.end())
+ return make_pair(true, nodeDecryptionKeyIt->second);
+ return make_pair(false, make_shared<OwnedMemory>());
+ }
+
void DatabaseStorage::setNodeDecryptionKey(const Hash &nodeHash, const DataView &decryptionKeyView)
{
bool nodeHasExistingEncryptionKey = nodeDecryptionKeyMap.find(nodeHash) != nodeDecryptionKeyMap.end();