aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Channel.cpp61
-rw-r--r--src/Command.cpp2
-rw-r--r--src/MessageBoard.cpp19
-rw-r--r--src/User.cpp35
-rw-r--r--src/main.cpp397
5 files changed, 296 insertions, 218 deletions
diff --git a/src/Channel.cpp b/src/Channel.cpp
index ed037a4..a63fcc4 100644
--- a/src/Channel.cpp
+++ b/src/Channel.cpp
@@ -1,5 +1,4 @@
#include "../include/Channel.hpp"
-#include <odhtdb/User.hpp>
#include <odhtdb/Database.hpp>
#include <odhtdb/bin2hex.hpp>
#include <cstring>
@@ -95,17 +94,15 @@ namespace dchat
void Channel::addMessage(const std::string &msg)
{
- if(database && localUser->type == User::Type::ONLINE)
+ if(database && localUser->type == User::Type::ONLINE_LOCAL_USER)
{
- auto localOnlineUser = static_cast<OnlineUser*>(localUser);
- assert(localOnlineUser->databaseUser->getType() == odhtdb::User::Type::LOCAL);
+ auto onlineLocalUser = static_cast<OnlineLocalUser*>(localUser);
sibs::SafeSerializer serializer;
serializer.add(ChannelDataType::ADD_MESSAGE);
serializer.add((const u8*)msg.data(), msg.size());
- database->addData(databaseNodeInfo, static_cast<const odhtdb::LocalUser*>(localOnlineUser->databaseUser), odhtdb::DataView(serializer.getBuffer().data(), serializer.getBuffer().size()));
- database->commit();
+ database->addData(databaseNodeInfo, onlineLocalUser->keyPair, odhtdb::DataView(serializer.getBuffer().data(), serializer.getBuffer().size()));
}
else
addLocalMessage(msg, localUser, 0, odhtdb::Hash());
@@ -118,17 +115,15 @@ namespace dchat
void Channel::deleteMessage(const odhtdb::Hash &id, const odhtdb::Signature::PublicKey &requestedByUser)
{
- if(database && localUser->type == User::Type::ONLINE)
+ if(database && localUser->type == User::Type::ONLINE_LOCAL_USER)
{
- auto localOnlineUser = static_cast<OnlineUser*>(localUser);
- assert(localOnlineUser->databaseUser->getType() == odhtdb::User::Type::LOCAL);
+ auto onlineLocalUser = static_cast<OnlineLocalUser*>(localUser);
sibs::SafeSerializer serializer;
serializer.add(ChannelDataType::DELETE_MESSAGE);
serializer.add((const u8*)id.getData(), odhtdb::HASH_BYTE_SIZE);
- database->addData(databaseNodeInfo, static_cast<const odhtdb::LocalUser*>(localOnlineUser->databaseUser), odhtdb::DataView(serializer.getBuffer().data(), serializer.getBuffer().size()));
- database->commit();
+ database->addData(databaseNodeInfo, onlineLocalUser->keyPair, odhtdb::DataView(serializer.getBuffer().data(), serializer.getBuffer().size()));
}
else
deleteLocalMessage(id, requestedByUser);
@@ -137,41 +132,39 @@ namespace dchat
void Channel::addUserLocally(User *user)
{
users.push_back(user);
- if(user->type == User::Type::ONLINE)
+ if(user->isOnlineUser())
{
auto onlineUser = static_cast<OnlineUser*>(user);
- publicKeyOnlineUsersMap[onlineUser->databaseUser->getPublicKey()] = onlineUser;
+ publicKeyOnlineUsersMap[onlineUser->getPublicKey()] = onlineUser;
}
}
- bool Channel::addUser(const odhtdb::Signature::PublicKey &userId, const string &groupId)
+ bool Channel::addUser(const odhtdb::Signature::PublicKey &userId, const odhtdb::DataView &groupId)
{
assert(database);
- if(!database || localUser->type != User::Type::ONLINE)
+ if(!database || localUser->type != User::Type::ONLINE_LOCAL_USER)
return false;
- if(groupId.size() != odhtdb::GROUP_ID_LENGTH)
+ if(groupId.size != odhtdb::GROUP_ID_LENGTH)
{
- fprintf(stderr, "Group id is wrong size. Expected to be %u bytes, was %u byte(s)\n", odhtdb::GROUP_ID_LENGTH, groupId.size());
+ fprintf(stderr, "Group id is wrong size. Expected to be %u bytes, was %u byte(s)\n", odhtdb::GROUP_ID_LENGTH, groupId.size);
return false;
}
- auto localOnlineUser = static_cast<OnlineUser*>(localUser);
- assert(localOnlineUser->databaseUser->getType() == odhtdb::User::Type::LOCAL);
-
- uint8_t groupIdRaw[odhtdb::GROUP_ID_LENGTH];
- memcpy(groupIdRaw, groupId.data(), groupId.size());
- auto groupToAddUserTo = database->getStorage().getGroupById(*databaseNodeInfo.getRequestHash(), groupIdRaw);
- if(!groupToAddUserTo)
+ auto onlineLocalUser = static_cast<OnlineLocalUser*>(localUser);
+ try
+ {
+ database->addUser(databaseNodeInfo, onlineLocalUser->keyPair, userId, groupId);
+ return true;
+ }
+ catch(std::exception &e)
{
- fprintf(stderr, "Group with id %s does not exist in channel %s\n", odhtdb::bin2hex(groupId.c_str(), groupId.size()).c_str(), databaseNodeInfo.getRequestHash()->toString().c_str());
+ fprintf(stderr, "Group with id %s does not exist in channel %s or you do not have permission to add user to that group\nError: %s\n", odhtdb::bin2hex((const char*)groupId.data, groupId.size).c_str(), databaseNodeInfo.getRequestHash()->toString().c_str(), e.what());
return false;
}
- database->addUser(databaseNodeInfo, static_cast<const odhtdb::LocalUser*>(localOnlineUser->databaseUser), "noname", userId, groupToAddUserTo);
- return true;
}
- void Channel::replaceLocalUser(User *newLocalUser)
+ void Channel::replaceLocalUser(OnlineLocalUser *newOnlineLocalUser)
{
for(vector<User*>::iterator it = users.begin(); it != users.end(); ++it)
{
@@ -183,24 +176,22 @@ namespace dchat
}
}
- localUser = newLocalUser;
- addUserLocally(newLocalUser);
+ localUser = newOnlineLocalUser;
+ addUserLocally(newOnlineLocalUser);
}
void Channel::changeNick(const std::string &newNick)
{
- if(database && localUser->type == User::Type::ONLINE)
+ if(database && localUser->type == User::Type::ONLINE_LOCAL_USER)
{
- auto localOnlineUser = static_cast<OnlineUser*>(localUser);
- assert(localOnlineUser->databaseUser->getType() == odhtdb::User::Type::LOCAL);
+ auto onlineLocalUser = static_cast<OnlineLocalUser*>(localUser);
sibs::SafeSerializer serializer;
serializer.add(ChannelDataType::NICKNAME_CHANGE);
serializer.add((u8)newNick.size());
serializer.add((const u8*)newNick.data(), newNick.size());
- database->addData(databaseNodeInfo, static_cast<const odhtdb::LocalUser*>(localOnlineUser->databaseUser), odhtdb::DataView(serializer.getBuffer().data(), serializer.getBuffer().size()));
- database->commit();
+ database->addData(databaseNodeInfo, onlineLocalUser->keyPair, odhtdb::DataView(serializer.getBuffer().data(), serializer.getBuffer().size()));
}
}
diff --git a/src/Command.cpp b/src/Command.cpp
index a074930..a28cd42 100644
--- a/src/Command.cpp
+++ b/src/Command.cpp
@@ -5,7 +5,7 @@ using namespace std;
namespace dchat
{
- unordered_map<string, CommandHandlerFunc> commandHandlerFuncs;
+ static unordered_map<string, CommandHandlerFunc> commandHandlerFuncs;
bool Command::add(const string &cmd, CommandHandlerFunc handlerFunc)
{
diff --git a/src/MessageBoard.cpp b/src/MessageBoard.cpp
index 46b9d28..b1f8b0b 100644
--- a/src/MessageBoard.cpp
+++ b/src/MessageBoard.cpp
@@ -16,7 +16,6 @@
#include <SFML/Window/Mouse.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Text.hpp>
-#include <odhtdb/User.hpp>
#include <cmath>
using namespace std;
@@ -82,12 +81,12 @@ namespace dchat
lock_guard<mutex> lock(messageProcessMutex);
auto it = messageIdMap.find(id);
if(it == messageIdMap.end()) return;
- if(it->second->user->type == User::Type::ONLINE)
+ if(it->second->user->isOnlineUser())
{
auto onlineUser = static_cast<const OnlineUser*>(it->second->user);
- if(onlineUser->databaseUser->getPublicKey() != requestedByUser)
+ if(onlineUser->getPublicKey() != requestedByUser)
{
- fprintf(stderr, "Warning: user %s requested to delete a message owned by user %s, ignoring request\n", requestedByUser.toString().c_str(), onlineUser->databaseUser->getPublicKey().toString().c_str());
+ fprintf(stderr, "Warning: user %s requested to delete a message owned by user %s, ignoring request\n", requestedByUser.toString().c_str(), onlineUser->getPublicKey().toString().c_str());
return;
}
}
@@ -292,11 +291,11 @@ namespace dchat
message->text.processEvent(event);
}
- OnlineUser *localOnlineUser = nullptr;
- if(channel->getLocalUser()->type == User::Type::ONLINE)
- localOnlineUser = static_cast<OnlineUser*>(channel->getLocalUser());
+ OnlineLocalUser *onlineLocalUser = nullptr;
+ if(channel->getLocalUser()->type == User::Type::ONLINE_LOCAL_USER)
+ onlineLocalUser = static_cast<OnlineLocalUser*>(channel->getLocalUser());
- if(localOnlineUser && event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Button::Right)
+ if(onlineLocalUser && event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Button::Right)
{
for(auto it : messageIdMap)
{
@@ -307,9 +306,9 @@ namespace dchat
auto contextMenu = GlobalContextMenu::getEditMessageContextMenu();
contextMenu->setPosition(sf::Vector2f(event.mouseButton.x, event.mouseButton.y));
contextMenu->setVisible(true);
- GlobalContextMenu::setClickDeleteMessageCallbackFunc([this, it, localOnlineUser](ContextMenuItem *menuItem)
+ GlobalContextMenu::setClickDeleteMessageCallbackFunc([this, it, onlineLocalUser](ContextMenuItem *menuItem)
{
- channel->deleteMessage(it.first, localOnlineUser->databaseUser->getPublicKey());
+ channel->deleteMessage(it.first, onlineLocalUser->getPublicKey());
GlobalContextMenu::setClickDeleteMessageCallbackFunc(nullptr);
});
return;
diff --git a/src/User.cpp b/src/User.cpp
index 16b3648..986380c 100644
--- a/src/User.cpp
+++ b/src/User.cpp
@@ -1,6 +1,4 @@
#include "../include/User.hpp"
-#include <odhtdb/User.hpp>
-#include <cassert>
namespace dchat
{
@@ -12,18 +10,41 @@ namespace dchat
}
- OnlineUser::OnlineUser(const odhtdb::User *_databaseUser) :
- User(Type::ONLINE),
- name("randomUser69"),
- databaseUser(_databaseUser)
+ OnlineUser::OnlineUser(const std::string &_name, Type type) :
+ User(type),
+ name(_name)
{
- assert(databaseUser);
+
}
const std::string& OnlineUser::getName() const
{
return name;
}
+
+ OnlineRemoteUser::OnlineRemoteUser(const std::string &name, const odhtdb::Signature::PublicKey &_publicKey) :
+ OnlineUser(name, Type::ONLINE_REMOTE_USER),
+ publicKey(_publicKey)
+ {
+
+ }
+
+ const odhtdb::Signature::PublicKey& OnlineRemoteUser::getPublicKey() const
+ {
+ return publicKey;
+ }
+
+ OnlineLocalUser::OnlineLocalUser(const std::string &name, const odhtdb::Signature::KeyPair &_keyPair) :
+ OnlineUser(name, Type::ONLINE_LOCAL_USER),
+ keyPair(_keyPair)
+ {
+
+ }
+
+ const odhtdb::Signature::PublicKey& OnlineLocalUser::getPublicKey() const
+ {
+ return keyPair.getPublicKey();
+ }
OfflineUser::OfflineUser(const std::string &_name) :
User(Type::OFFLINE),
diff --git a/src/main.cpp b/src/main.cpp
index 18f10fe..249c5d4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -18,6 +18,7 @@
#include <odhtdb/bin2hex.hpp>
#include <odhtdb/hex2bin.hpp>
#include <ntp/NtpClient.hpp>
+#include <sibs/SafeSerializer.hpp>
#include <X11/Xlib.h>
using namespace std;
@@ -128,19 +129,6 @@ void channelAddStoredMessage(Channel *channel, const odhtdb::Hash &requestHash,
}
}
-void channelAddStoredMessages(Channel *channel, const odhtdb::DatabaseStorageObjectList *nodeStorage)
-{
- printf("Load %u message(s) in channel %s\n", nodeStorage->objects.size(), channel->getName().c_str());
- for(auto nodeStorageAddedObject : nodeStorage->objects)
- {
- if(nodeStorageAddedObject->decryptedObject.operation == odhtdb::DatabaseOperation::ADD_DATA)
- {
- StringView decryptedObject((const char*)nodeStorageAddedObject->decryptedObject.data.data, nodeStorageAddedObject->decryptedObject.data.size);
- channelAddStoredMessage(channel, nodeStorageAddedObject->requestHash, nodeStorageAddedObject->creatorPublicKey, decryptedObject, nodeStorageAddedObject->createdTimestamp);
- }
- }
-}
-
int main(int argc, char **argv)
{
/*
@@ -158,8 +146,6 @@ int main(int argc, char **argv)
window.setVerticalSyncEnabled(false);
window.setFramerateLimit(FRAMERATE_FOCUSED);
- odhtdb::Database database("bootstrap.ring.cx", 4222, Cache::getDchatDir());
-
//Video video(500, 500, "https://www.youtube.com/watch?v=bs0-EX9mJmg");
Cache cache;
@@ -171,51 +157,69 @@ int main(int argc, char **argv)
vector<Channel*> channels;
- odhtdb::Signature::KeyPair *currentUserKeyPair = nullptr;
- vector<odhtdb::NodeLocalUser> localNodeUsers;
vector<odhtdb::DatabaseNode> waitingToJoinChannels;
- string currentUserName;
- string currentUserPassword;
+ odhtdb::MapHash<odhtdb::StoredNodeInfo> localNodeUsers;
+ string currentUsername;
+ string currentPassword;
recursive_mutex channelMessageMutex;
bool waitingToJoin = false;
+ bool loggedIn = false;
+
+ odhtdb::Database *database = nullptr;
+ odhtdb::DatabaseCallbackFuncs callbackFuncs;
- database.setOnCreateNodeCallback([&waitingToJoinChannels, &database, &channels, &channelMessageMutex, &waitingToJoin](const odhtdb::DatabaseCreateNodeRequest &request)
+ callbackFuncs.createNodeCallbackFunc = [&waitingToJoinChannels, &database, &channels, &channelMessageMutex, &waitingToJoin, &localNodeUsers](const odhtdb::DatabaseCreateNodeRequest &request)
{
lock_guard<recursive_mutex> lock(channelMessageMutex);
+
+ auto nodeUserData = localNodeUsers.find(*request.nodeHash);
+ if(nodeUserData == localNodeUsers.end()) return;
+
+ User *localUser;
+ if(nodeUserData->second.userKeyPair->getPublicKey() == *request.creatorPublicKey)
+ localUser = new OnlineLocalUser("NoName", *nodeUserData->second.userKeyPair);
+ else
+ localUser = new OfflineUser("You");
+
+ shared_ptr<odhtdb::Hash> databaseNodeHash = make_shared<odhtdb::Hash>();
+ memcpy(databaseNodeHash->getData(), request.nodeHash->getData(), odhtdb::HASH_BYTE_SIZE);
+ odhtdb::DatabaseNode databaseNode(nodeUserData->second.nodeEncryptionKey, databaseNodeHash);
+ Channel *channel = new Channel("NoChannelName", databaseNode, localUser, database);
+ ChannelSidePanel::addChannel(channel);
+ channels.push_back(channel);
+ Channel::setCurrent(channel);
+
+ if(localUser->type == User::Type::OFFLINE)
+ {
+ User *nodeCreatorUser = new OnlineRemoteUser("NoName", *request.creatorPublicKey);
+ channel->addUserLocally(nodeCreatorUser);
+ }
+
for(vector<odhtdb::DatabaseNode>::iterator it = waitingToJoinChannels.begin(); it != waitingToJoinChannels.end(); ++it)
{
if(*request.nodeHash == *it->getRequestHash())
{
- User *localUser = new OfflineUser("You");
- Channel *channel = new Channel(request.name, *it, localUser, &database);
- ChannelSidePanel::addChannel(channel);
- channels.push_back(channel);
- Channel::setCurrent(channel);
-
- User *nodeCreatorUser = new OnlineUser(request.creatorUser);
- channel->addUserLocally(nodeCreatorUser);
waitingToJoin = true;
-
waitingToJoinChannels.erase(it);
return;
}
}
- });
+ };
- database.setOnAddNodeCallback([&channels, &channelMessageMutex](const odhtdb::DatabaseAddNodeRequest &request)
+ callbackFuncs.addNodeCallbackFunc = [&channels, &channelMessageMutex](const odhtdb::DatabaseAddNodeRequest &request)
{
lock_guard<recursive_mutex> lock(channelMessageMutex);
for(Channel *channel : channels)
{
if(*request.nodeHash == *channel->getNodeInfo().getRequestHash())
{
- channelAddStoredMessage(channel, *request.requestHash, request.creatorUser->getPublicKey(), StringView((const char*)request.decryptedData.data, request.decryptedData.size), request.timestamp);
+ channelAddStoredMessage(channel, *request.requestHash, *request.creatorPublicKey, StringView((const char*)request.decryptedData.data, request.decryptedData.size), request.timestamp);
return;
}
}
- });
+ };
- database.setOnAddUserCallback([&currentUserKeyPair, &channels, &channelMessageMutex, &waitingToJoin, &database](const odhtdb::DatabaseAddUserRequest &request)
+ callbackFuncs.addUserCallbackFunc = [&channels, &channelMessageMutex, &waitingToJoin, &localNodeUsers](const odhtdb::DatabaseAddUserRequest &request)
{
lock_guard<recursive_mutex> lock(channelMessageMutex);
printf("Add user callback. Channel to add user to: %s\n", request.nodeHash->toString().c_str());
@@ -225,34 +229,35 @@ int main(int argc, char **argv)
if(*request.nodeHash == *channel->getNodeInfo().getRequestHash())
{
printf("Add user to one of my channels\n");
- if(currentUserKeyPair && request.userToAdd->getPublicKey() == currentUserKeyPair->getPublicKey() && channel->getLocalUser()->type != User::Type::ONLINE)
+ auto nodeUserData = localNodeUsers.find(*request.nodeHash);
+
+ User *userToAdd = channel->getUserByPublicKey(*request.userToAddPublicKey);
+ if(userToAdd)
{
- // Replace remote user with local user, if we are the remote user
- database.getStorage().getLocalNodeUsers(*currentUserKeyPair);
- auto userToAdd = database.getStorage().getUserByPublicKey(*request.nodeHash, currentUserKeyPair->getPublicKey());
- printf("You were added to channel %s by %s\n", request.nodeHash->toString().c_str(), request.creatorUser->getName().c_str());
- channel->replaceLocalUser(new OnlineUser(userToAdd));
- waitingToJoin = false;
+ fprintf(stderr, "User %s already exists in channel\n", request.userToAddPublicKey->toString().c_str());
return;
}
- User *userToAdd = channel->getUserByPublicKey(request.userToAdd->getPublicKey());
- if(userToAdd)
+ if(*request.userToAddPublicKey == nodeUserData->second.userKeyPair->getPublicKey())
{
- fprintf(stderr, "User %s already exists in channel\n", request.userToAdd->getPublicKey().toString().c_str());
+ printf("You were added to channel %s by %s\n", request.nodeHash->toString().c_str(), request.creatorPublicKey->toString().c_str());
+ channel->replaceLocalUser(new OnlineLocalUser("NoName", *nodeUserData->second.userKeyPair));
+ waitingToJoin = false;
return;
}
- User *newRemoteUser = new OnlineUser(request.userToAdd);
+ User *newRemoteUser = new OnlineRemoteUser("NoName", *request.userToAddPublicKey);
channel->addUserLocally(newRemoteUser);
return;
}
}
- });
+ };
+ database = new odhtdb::Database("bootstrap.ring.cx", 4222, Cache::getDchatDir(), callbackFuncs);
// Login to account
- Command::add("login", [&currentUserKeyPair, &currentUserName, &currentUserPassword, &localNodeUsers, &database, &channels, &channelMessageMutex](const vector<string> &args)
+ Command::add("login", [&localNodeUsers, &database, &channels, &loggedIn, &channelMessageMutex, &currentUsername, &currentPassword](const vector<string> &args)
{
+ lock_guard<recursive_mutex> lock(channelMessageMutex);
if(args.size() != 2)
{
fprintf(stderr, "Expected 2 arguments for command login (username and password), got %u argument(s)\n", args.size());
@@ -261,8 +266,7 @@ int main(int argc, char **argv)
try
{
- odhtdb::Signature::KeyPair keyPair = database.getStorage().decryptLocalEncryptedUser(args[0], args[1]);
- localNodeUsers = database.getStorage().getLocalNodeUsers(keyPair);
+ localNodeUsers = database->getStoredNodeUserInfoDecrypted(args[0], args[1]);
ChannelSidePanel::removeAllChannels();
for(Channel *channel : channels)
@@ -271,51 +275,25 @@ int main(int argc, char **argv)
}
channels.clear();
- lock_guard<recursive_mutex> lock(channelMessageMutex);
- for(auto localNodeUser : localNodeUsers)
+ printf("Loading %u channel(s) for user\n", localNodeUsers.size());
+ for(auto &localNodeUser : localNodeUsers)
{
- auto nodeStorage = database.getStorage().getStorage(localNodeUser.nodeHash);
- if(!nodeStorage) continue;
-
- auto nodeDecryptionKeyResult = database.getStorage().getNodeDecryptionKey(localNodeUser.nodeHash);
- if(!nodeDecryptionKeyResult.first) continue;
-
- User *newLocalUser = new OnlineUser(localNodeUser.localUser);
- odhtdb::DatabaseNode databaseNode(nodeDecryptionKeyResult.second, make_shared<odhtdb::Hash>(localNodeUser.nodeHash));
- Channel *channel = new Channel(nodeStorage->nodeName, databaseNode, newLocalUser, &database);
-
- auto nodeUserMapByPublicKey = database.getStorage().getNodeUsers(localNodeUser.nodeHash);
- for(auto nodeUserIt : *nodeUserMapByPublicKey)
- {
- if(nodeUserIt.second != localNodeUser.localUser)
- {
- User *newRemoteUser = new OnlineUser(nodeUserIt.second);
- channel->addUserLocally(newRemoteUser);
- }
- }
-
- ChannelSidePanel::addChannel(channel);
- channels.push_back(channel);
- Channel::setCurrent(channel);
- channelAddStoredMessages(channel, nodeStorage);
+ database->loadNode(localNodeUser.first);
}
printf("Successfully logged into user %s\n", args[0].c_str());
- if(currentUserKeyPair)
- delete currentUserKeyPair;
- currentUserKeyPair = new odhtdb::Signature::KeyPair(keyPair);
-
- currentUserName = args[0];
- currentUserPassword = args[1];
+ currentUsername = args[0];
+ currentPassword = args[1];
+ loggedIn = true;
}
- catch(odhtdb::DatabaseStorageException &e)
+ catch(std::exception &e)
{
fprintf(stderr, "Failed to login, reason: %s\n", e.what());
}
});
// Register account
- Command::add("register", [&currentUserKeyPair, &currentUserName, &currentUserPassword, &localNodeUsers, &database, &channelMessageMutex](const vector<string> &args)
+ Command::add("register", [&localNodeUsers, &database, &channels, &loggedIn, &channelMessageMutex, &currentUsername, &currentPassword](const vector<string> &args)
{
lock_guard<recursive_mutex> lock(channelMessageMutex);
if(args.size() != 2)
@@ -324,33 +302,34 @@ int main(int argc, char **argv)
return;
}
- if(currentUserKeyPair)
+ try
{
- fprintf(stderr, "You can't register a new account when you are logged in, please logout first\n");
- return;
+ database->storeUserWithoutNodes(args[0], args[1]);
}
-
- odhtdb::Signature::KeyPair keyPair;
- if(!database.getStorage().storeLocalUser(args[0], keyPair, args[1]))
+ catch(odhtdb::SqlExecException &e)
{
fprintf(stderr, "User with name %s already exists in storage\n", args[0].c_str());
return;
}
- printf("Registered user %s, public key: %s, private key: %s\n", args[0].c_str(), keyPair.getPublicKey().toString().c_str(), keyPair.getPrivateKey().toString().c_str());
- printf("Successfully logged into user %s\n", args[0].c_str());
+ printf("Registered user %s\n", args[0].c_str());
- if(currentUserKeyPair)
- delete currentUserKeyPair;
- currentUserKeyPair = new odhtdb::Signature::KeyPair(keyPair);
+ ChannelSidePanel::removeAllChannels();
+ for(Channel *channel : channels)
+ {
+ delete channel;
+ }
+ channels.clear();
localNodeUsers.clear();
- currentUserName = args[0];
- currentUserPassword = args[1];
+ printf("Successfully logged into user %s\n", args[0].c_str());
+ currentUsername = args[0];
+ currentPassword = args[1];
+ loggedIn = true;
});
// Create channel
- Command::add("cc", [&currentUserKeyPair, &currentUserName, &database, &channels, &channelMessageMutex](const vector<string> &args)
+ Command::add("cc", [&database, &channels, &channelMessageMutex, &loggedIn, &localNodeUsers, &currentUsername, &currentPassword](const vector<string> &args)
{
lock_guard<recursive_mutex> lock(channelMessageMutex);
if(args.size() != 1)
@@ -359,69 +338,113 @@ int main(int argc, char **argv)
return;
}
- if(!currentUserKeyPair)
+ if(!loggedIn)
{
fprintf(stderr, "You are not logged in. Please login before creating a channel\n");
return;
}
- auto createResponse = database.create(currentUserName, *currentUserKeyPair, args[0]);
- database.commit();
+ auto createResponse = database->create();
printf("Created database '%s', join key: '%s'\n", args[0].c_str(), createChannelJoinKey(createResponse).c_str());
- User *newLocalUser = new OnlineUser(createResponse->getNodeAdminUser());
+ User *newLocalUser = new OnlineLocalUser("NoName", *createResponse->getNodeAdminKeyPair());
odhtdb::DatabaseNode databaseNode(createResponse->getNodeEncryptionKey(), createResponse->getRequestHash());
- Channel *channel = new Channel(args[0], databaseNode, newLocalUser, &database);
+ Channel *channel = new Channel(args[0], databaseNode, newLocalUser, database);
ChannelSidePanel::addChannel(channel);
channels.push_back(channel);
Channel::setCurrent(channel);
+
+ localNodeUsers[*createResponse->getRequestHash()] = { createResponse->getNodeEncryptionKey(), createResponse->getNodeAdminKeyPair() };
+ database->storeNodeInfoForUserEncrypted(databaseNode, currentUsername, currentPassword, *createResponse->getNodeAdminKeyPair());
+ Channel::getCurrent()->addLocalMessage("Channel created and stored in database", Channel::getCurrent()->getSystemUser());
});
- // Add user
- Command::add("au", [&offlineChannel, &channelMessageMutex](const vector<string> &args)
+ // Create invite key
+ Command::add("invite", [&channelMessageMutex, &offlineChannel, &database](const vector<string> &args)
{
lock_guard<recursive_mutex> lock(channelMessageMutex);
- if(args.size() != 2)
- {
- fprintf(stderr, "Expected 2 arguments for command au (user id, group id), got %u argument(s)\n", args.size());
- return;
- }
-
- if(args[0].size() != odhtdb::PUBLIC_KEY_NUM_BYTES * 2)
- {
- fprintf(stderr, "User id is wrong size. Expected to be %u characters, was %u character(s)\n", odhtdb::PUBLIC_KEY_NUM_BYTES * 2, args[0].size());
- return;
- }
-
- if(args[1].size() != odhtdb::GROUP_ID_LENGTH * 2)
+ if(args.size() != 0)
{
- fprintf(stderr, "Group id is wrong size. Expected to be %u characters, was %u character(s)\n", odhtdb::GROUP_ID_LENGTH * 2, args[1].size());
+ fprintf(stderr, "Expected 0 arguments for command invite, got %u argument(s)\n", args.size());
return;
}
Channel *currentChannel = Channel::getCurrent();
if(currentChannel == &offlineChannel)
{
- Channel::getCurrent()->addLocalMessage("You need to be in a channel to add user to the channel", Channel::getCurrent()->getSystemUser());
+ Channel::getCurrent()->addLocalMessage("You need to be in a channel to create an invite key", Channel::getCurrent()->getSystemUser());
return;
}
- auto userIdRaw = odhtdb::hex2bin(args[0].c_str(), args[0].size());
- odhtdb::Signature::PublicKey userPublicKey(userIdRaw.data(), userIdRaw.size());
+ // TODO: Verify user has permission to add users before generating invite key, otherwise invite will fail and the users attempting to join will wait in futile
- auto groupIdRaw = odhtdb::hex2bin(args[1].c_str(), args[1].size());
- bool userAddResult = currentChannel->addUser(userPublicKey, groupIdRaw);
- if(userAddResult)
- {
- printf("Added user to your channel!\n");
- }
- else
+ auto channelNodeHash = currentChannel->getNodeInfo().getRequestHash();
+ auto channelEncryptionKey = currentChannel->getNodeInfo().getNodeEncryptionKey();
+ shared_ptr<odhtdb::OwnedMemory> encryptionKey = make_shared<odhtdb::OwnedMemory>(new u8[odhtdb::ENCRYPTION_KEY_BYTE_SIZE], odhtdb::ENCRYPTION_KEY_BYTE_SIZE);
+ odhtdb::Encryption::generateKey((unsigned char*)encryptionKey->data);
+
+ string inviteKey = odhtdb::bin2hex((const char*)channelNodeHash->getData(), channelNodeHash->getSize());
+ inviteKey += '&';
+ inviteKey += odhtdb::bin2hex((const char*)encryptionKey->data, odhtdb::ENCRYPTION_KEY_BYTE_SIZE);
+
+ string msg = "You are now listening for users to join the channel using the key: ";
+ msg += inviteKey;
+
+ Channel::getCurrent()->addLocalMessage(msg, Channel::getCurrent()->getSystemUser());
+ printf("%s\n", msg.c_str());
+
+ sibs::SafeSerializer keySerializer;
+ keySerializer.add((const u8*)channelNodeHash->getData(), channelNodeHash->getSize());
+ keySerializer.add((const u8*)encryptionKey->data, odhtdb::ENCRYPTION_KEY_BYTE_SIZE);
+ dht::InfoHash key = odhtdb::Database::getInfoHash(keySerializer.getBuffer().data(), keySerializer.getBuffer().size());
+ database->receiveCustomMessage(key, [&channelMessageMutex, encryptionKey, channelEncryptionKey, currentChannel, &database](const void *data, usize size)
{
- fprintf(stderr, "Failed to add user to your channel!\n");
- }
+ // TODO: User can remove channel @currentChannel before we get here, meaning @currentChannel is deleted and would be invalid; causing the program to crash
+ try
+ {
+ sibs::SafeDeserializer deserializer((const u8*)data, size);
+ u8 userToAddPublicKeyRaw[odhtdb::PUBLIC_KEY_NUM_BYTES];
+ deserializer.extract(userToAddPublicKeyRaw, odhtdb::PUBLIC_KEY_NUM_BYTES);
+ odhtdb::Signature::PublicKey userToAddPublicKey((const char*)userToAddPublicKeyRaw, odhtdb::PUBLIC_KEY_NUM_BYTES);
+ string unsignedEncryptedMsg = userToAddPublicKey.unsign(odhtdb::DataView((void*)deserializer.getBuffer(), deserializer.getSize()));
+
+ sibs::SafeDeserializer encryptedDataDeserializer((const u8*)unsignedEncryptedMsg.data(), unsignedEncryptedMsg.size());
+ u8 nonce[odhtdb::ENCRYPTION_NONCE_BYTE_SIZE];
+ encryptedDataDeserializer.extract(nonce, odhtdb::ENCRYPTION_NONCE_BYTE_SIZE);
+ odhtdb::Decryption decryptedMsg(odhtdb::DataView((void*)encryptedDataDeserializer.getBuffer(), encryptedDataDeserializer.getSize()),
+ odhtdb::DataView(nonce, odhtdb::ENCRYPTION_NONCE_BYTE_SIZE),
+ encryptionKey->getView());
+
+ // TODO: Create GUI for accepting users into channel instead of accepting ALL users
+ sibs::SafeSerializer encryptedDataSerializer;
+ encryptedDataSerializer.add((const u8*)channelEncryptionKey->data, channelEncryptionKey->size);
+ encryptedDataSerializer.add((const u8*)userToAddPublicKey.getData(), userToAddPublicKey.getSize());
+ odhtdb::Encryption encryptedChannelKey(odhtdb::DataView((void*)encryptedDataSerializer.getBuffer().data(), encryptedDataSerializer.getBuffer().size()), encryptionKey->getView());
+
+ sibs::SafeSerializer serializer;
+ serializer.add((const u8*)encryptedChannelKey.getNonce().data, encryptedChannelKey.getNonce().size);
+ serializer.add((const u8*)encryptedChannelKey.getCipherText().data, encryptedChannelKey.getCipherText().size);
+ const auto &localUserPublicKey = static_cast<OnlineLocalUser*>(currentChannel->getLocalUser())->getPublicKey();
+ auto localUserGroups = database->getUserGroups(*currentChannel->getNodeInfo().getRequestHash(), localUserPublicKey);
+ if(!localUserGroups.empty())
+ {
+ fprintf(stderr, "No group to add user to...\n");
+ return sibs::SafeSerializer();
+ }
+ lock_guard<recursive_mutex> lock(channelMessageMutex);
+ currentChannel->addUser(localUserPublicKey, localUserGroups[0].getView());
+ return serializer;
+ }
+ catch(std::exception &e)
+ {
+ fprintf(stderr, "Failed while parsing user data to add to channel, reason: %s\n", e.what());
+ }
+ return sibs::SafeSerializer();
+ });
});
- Command::add("jc", [&currentUserKeyPair, &database, &localNodeUsers, &channelMessageMutex, &waitingToJoin, &waitingToJoinChannels](const vector<string> &args)
+ // Join channel using invite key
+ Command::add("jc", [&loggedIn, &database, &localNodeUsers, &channelMessageMutex, &waitingToJoin, &waitingToJoinChannels, &currentUsername, &currentPassword](const vector<string> &args)
{
lock_guard<recursive_mutex> lock(channelMessageMutex);
if(args.size() != 1)
@@ -436,29 +459,90 @@ int main(int argc, char **argv)
return;
}
- if(!currentUserKeyPair)
+ if(!loggedIn)
{
fprintf(stderr, "You are not logged in. Please login before joining a channel\n");
return;
}
- odhtdb::DatabaseNode databaseNode = createDatabaseNodeFromJoinKey(args[0]);
- for(auto localNodeUser : localNodeUsers)
+ string nodeHashBinRaw = odhtdb::hex2bin(args[0].c_str(), 64);
+ shared_ptr<odhtdb::Hash> nodeHash = make_shared<odhtdb::Hash>();
+ memcpy(nodeHash->getData(), nodeHashBinRaw.data(), nodeHashBinRaw.size());
+ auto nodeUserIt = localNodeUsers.find(*nodeHash);
+ if(nodeUserIt != localNodeUsers.end())
{
- if(*databaseNode.getRequestHash() == localNodeUser.nodeHash)
- {
- fprintf(stderr, "You have already joined the channel %s\n", databaseNode.getRequestHash()->toString().c_str());
- return;
- }
+ fprintf(stderr, "You have already joined the channel %s\n", args[0].c_str());
+ return;
}
- database.seed(databaseNode);
- waitingToJoinChannels.push_back(databaseNode);
+ string encryptionKeyBinRaw = odhtdb::hex2bin(args[0].c_str() + 65, 64);
+ shared_ptr<odhtdb::OwnedMemory> encryptionKey = make_shared<odhtdb::OwnedMemory>(new u8[odhtdb::ENCRYPTION_KEY_BYTE_SIZE], odhtdb::ENCRYPTION_KEY_BYTE_SIZE);
+ memcpy(encryptionKey->data, encryptionKeyBinRaw.data(), encryptionKeyBinRaw.size());
+
+ shared_ptr<odhtdb::Signature::KeyPair> keyPair = make_shared<odhtdb::Signature::KeyPair>();
+ sibs::SafeSerializer serializer;
+ serializer.add((const u8*)keyPair->getPublicKey().getData(), keyPair->getPublicKey().getSize());
+
+ localNodeUsers[*nodeHash] = { encryptionKey, keyPair };
+
+ const char *msg = "please let me join";
+ odhtdb::Encryption encryptedJoinMsg(odhtdb::DataView((void*)msg, strlen(msg)), encryptionKey->getView());
+ sibs::SafeSerializer encryptedDataSerializer;
+ encryptedDataSerializer.add((const u8*)encryptedJoinMsg.getNonce().data, encryptedJoinMsg.getNonce().size);
+ encryptedDataSerializer.add((const u8*)encryptedJoinMsg.getCipherText().data, encryptedJoinMsg.getCipherText().size);
+ string signedEncryptedMsg = keyPair->getPrivateKey().sign(odhtdb::DataView(encryptedDataSerializer.getBuffer().data(), encryptedDataSerializer.getBuffer().size()));
+ serializer.add((const u8*)signedEncryptedMsg.data(), signedEncryptedMsg.size());
+
+ sibs::SafeSerializer keySerializer;
+ keySerializer.add((const u8*)nodeHash->getData(), nodeHash->getSize());
+ keySerializer.add((const u8*)encryptionKeyBinRaw.data(), odhtdb::ENCRYPTION_KEY_BYTE_SIZE);
+ dht::InfoHash key = odhtdb::Database::getInfoHash(keySerializer.getBuffer().data(), keySerializer.getBuffer().size());
+ database->sendCustomMessage(key, move(serializer.getBuffer()), [&database, nodeHash, encryptionKey, &waitingToJoinChannels, &channelMessageMutex, keyPair, &currentUsername, &currentPassword, &localNodeUsers](bool gotResponse, const void *data, usize size)
+ {
+ if(!gotResponse)
+ {
+ printf("We didn't get a response from anybody in the channel. Is there nobody that can add us (nobody with the permission required to do so or no online users) or is the node hash invalid?\n");
+ return false;
+ }
+
+ try
+ {
+ sibs::SafeDeserializer deserializer((const u8*)data, size);
+ u8 nonce[odhtdb::ENCRYPTION_NONCE_BYTE_SIZE];
+ deserializer.extract(nonce, odhtdb::ENCRYPTION_NONCE_BYTE_SIZE);
+ odhtdb::Decryption decryptedMsg(odhtdb::DataView((void*)deserializer.getBuffer(), deserializer.getSize()),
+ odhtdb::DataView(nonce, odhtdb::ENCRYPTION_NONCE_BYTE_SIZE),
+ encryptionKey->getView());
+ if(decryptedMsg.getDecryptedText().size != odhtdb::ENCRYPTION_KEY_BYTE_SIZE + odhtdb::PUBLIC_KEY_NUM_BYTES)
+ {
+ fprintf(stderr, "Invite response was of unexpected size, maybe it wasn't mean for us?\n");
+ return true;
+ }
+
+ odhtdb::DataView channelEncryptionKey(decryptedMsg.getDecryptedText().data, odhtdb::ENCRYPTION_KEY_BYTE_SIZE);
+ odhtdb::DataView invitedUserPublicKey((u8*)decryptedMsg.getDecryptedText().data + odhtdb::ENCRYPTION_KEY_BYTE_SIZE, odhtdb::PUBLIC_KEY_NUM_BYTES);
+ if(memcmp(keyPair->getPublicKey().getData(), invitedUserPublicKey.data, odhtdb::PUBLIC_KEY_NUM_BYTES) != 0)
+ {
+ fprintf(stderr, "Invite response was not meant for us\n");
+ return true;
+ }
+
+ odhtdb::DatabaseNode databaseNode(encryptionKey, nodeHash);
+ database->storeNodeInfoForUserEncrypted(databaseNode, currentUsername, currentPassword, *keyPair);
+ printf("Got a response from a person in the channel, we might get added...\n");
+ waitingToJoinChannels.push_back(databaseNode);
+ lock_guard<recursive_mutex> lock(channelMessageMutex);
+ database->seed(databaseNode);
+ return false;
+ }
+ catch(std::exception &e)
+ {
+ fprintf(stderr, "Failed while parsing join response for invite link, reason: %s\n", e.what());
+ }
+ return true;
+
+ });
waitingToJoin = true;
- // TODO: Add the channel to join to a pending join list in a file and remove from it when we have joined the channel.
- // The reason for doing that is so if we crash or lose internet connection before we have got `create node` request from remote peers,
- // then we need to start seeding again when we login. Once we have `create node` request, then it's added to local cache and when you login,
- // it will be used to seed the channel.
});
// Scale UI
@@ -556,25 +640,8 @@ int main(int argc, char **argv)
Channel::getCurrent()->addLocalMessage(msg, Channel::getCurrent()->getSystemUser());
});
- // Get username and id (public key)
- Command::add("whoami", [&currentUserKeyPair, &currentUserName](const vector<string> &args)
- {
- if(!currentUserKeyPair)
- {
- Channel::getCurrent()->addLocalMessage("You are not logged in", Channel::getCurrent()->getSystemUser());
- return;
- }
-
- string response = "Username: ";
- response += currentUserName;
- response += ", id: ";
- response += currentUserKeyPair->getPublicKey().toString();
- printf("%s\n", response.c_str());
- Channel::getCurrent()->addLocalMessage(response, Channel::getCurrent()->getSystemUser());
- });
-
// Change nick of current user in current channel
- Command::add("nick", [&currentUserKeyPair, &offlineChannel](const vector<string> &args)
+ Command::add("nick", [&loggedIn, &offlineChannel](const vector<string> &args)
{
if(args.size() != 1)
{
@@ -585,7 +652,7 @@ int main(int argc, char **argv)
return;
}
- if(!currentUserKeyPair)
+ if(!loggedIn)
{
Channel::getCurrent()->addLocalMessage("You need to be logged in to change your nickname", Channel::getCurrent()->getSystemUser());
return;
@@ -610,7 +677,7 @@ int main(int argc, char **argv)
});
// Get channel join key
- Command::add("joinkey", [&currentUserKeyPair, &currentUserName, &offlineChannel](const vector<string> &args)
+ Command::add("joinkey", [&offlineChannel](const vector<string> &args)
{
Channel *currentChannel = Channel::getCurrent();
if(!currentChannel || currentChannel == &offlineChannel)