From 431c1dcded16649c10331b9dc4e57f20067cea0b Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 1 May 2018 13:27:52 +0200 Subject: Add 'add user', 'join channel'. Improve scrolling. Added locks --- src/main.cpp | 251 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 202 insertions(+), 49 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 364b2a9..7245b6e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,6 +47,19 @@ odhtdb::DatabaseNode createDatabaseNodeFromJoinKey(const string &joinKey) return result; } +void channelAddStoredMessage(Channel *channel, odhtdb::DatabaseStorageObject *nodeStorageObject) +{ + User *user = channel->getUserByPublicKey(nodeStorageObject->creatorPublicKey); + if(!user) + { + fprintf(stderr, "Missing user? %s\n", nodeStorageObject->creatorPublicKey.toString().c_str()); + return; + } + + string msg((const char*)nodeStorageObject->decryptedObject.data.data, nodeStorageObject->decryptedObject.data.size); + channel->addLocalMessage(msg, user, ntp::NtpTimestamp::fromCombined(nodeStorageObject->createdTimestamp).seconds); +} + void channelAddStoredMessages(Channel *channel, const odhtdb::DatabaseStorageObjectList *nodeStorage) { printf("Load %u messages in channel %s\n", nodeStorage->objects.size(), channel->getName().c_str()); @@ -54,14 +67,7 @@ void channelAddStoredMessages(Channel *channel, const odhtdb::DatabaseStorageObj { if(nodeStorageAddedObject->decryptedObject.operation == odhtdb::DatabaseOperation::ADD_DATA) { - User *user = channel->getUserByPublicKey(nodeStorageAddedObject->creatorPublicKey); - if(!user) - { - fprintf(stderr, "Missing user? %s\n", nodeStorageAddedObject->creatorPublicKey.toString().c_str()); - continue; - } - string msg((const char*)nodeStorageAddedObject->decryptedObject.data.data, nodeStorageAddedObject->decryptedObject.data.size); - channel->addLocalMessage(msg, user, ntp::NtpTimestamp::fromCombined(nodeStorageAddedObject->createdTimestamp).seconds); + channelAddStoredMessage(channel, nodeStorageAddedObject); } } } @@ -75,27 +81,16 @@ int main(int argc, char **argv) boost::filesystem::current_path(parentPath); // Ensures loading of resources works no matter which path we run this executable from */ + const int FRAMERATE_FOCUSED = 200; + const int FRAMERATE_NOT_FOCUSED = 30; + XInitThreads(); sf::RenderWindow window(sf::VideoMode(1920, 1080), "dchat"); window.setVerticalSyncEnabled(false); - window.setFramerateLimit(60); + window.setFramerateLimit(FRAMERATE_FOCUSED); odhtdb::Database database("bootstrap.ring.cx", 4222, Cache::getDchatDir()); - database.setOnCreateNodeCallback([](const odhtdb::DatabaseCreateNodeRequest &request) - { - - }); - - database.setOnAddNodeCallback([](const odhtdb::DatabaseAddNodeRequest &request) - { - - }); - - database.setOnAddUserCallback([](const odhtdb::DatabaseAddUserRequest &request) - { - - }); //Video video(500, 500, "https://www.youtube.com/watch?v=bs0-EX9mJmg"); Cache cache; @@ -108,10 +103,89 @@ int main(int argc, char **argv) odhtdb::Signature::KeyPair *currentUserKeyPair = nullptr; vector localNodeUsers; + vector waitingToJoinChannels; string currentUserName; string currentUserPassword; + recursive_mutex channelMessageMutex; + + database.setOnCreateNodeCallback([&waitingToJoinChannels, &database, &channels, &channelMessageMutex](const odhtdb::DatabaseCreateNodeRequest &request) + { + lock_guard lock(channelMessageMutex); + for(vector::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); + + waitingToJoinChannels.erase(it); + return; + } + } + }); + + database.setOnAddNodeCallback([&channels, &channelMessageMutex](const odhtdb::DatabaseAddNodeRequest &request) + { + lock_guard lock(channelMessageMutex); + for(Channel *channel : channels) + { + if(*request.nodeHash == *channel->getId()) + { + User *user = channel->getUserByPublicKey(request.creatorUser->getPublicKey()); + if(!user) + { + fprintf(stderr, "Missing user? %s\n", request.creatorUser->getPublicKey().toString().c_str()); + return; + } + + string msg((const char*)request.decryptedData.data, request.decryptedData.size); + channel->addLocalMessage(msg, user, ntp::NtpTimestamp::fromCombined(request.timestamp).seconds); + return; + } + } + }); + + database.setOnAddUserCallback([¤tUserKeyPair, &channels, &channelMessageMutex](const odhtdb::DatabaseAddUserRequest &request) + { + lock_guard lock(channelMessageMutex); + if(currentUserKeyPair && request.userToAdd->getPublicKey() == currentUserKeyPair->getPublicKey()) + { + printf("You were added to channel %s by %s\n", request.nodeHash->toString().c_str(), request.creatorUser->getName().c_str()); + return; + } + + for(Channel *channel : channels) + { + if(*request.nodeHash == *channel->getId()) + { + User *userToAdd = channel->getUserByPublicKey(request.userToAdd->getPublicKey()); + if(userToAdd && currentUserKeyPair && request.userToAdd->getPublicKey() == currentUserKeyPair->getPublicKey() && channel->getLocalUser()->type != User::Type::ONLINE) + { + channel->replaceLocalUser(new OnlineUser(request.userToAdd)); + return; + } + + if(userToAdd) + { + fprintf(stderr, "User %s already exists in channel\n", request.userToAdd->getPublicKey().toString().c_str()); + return; + } + + User *newRemoteUser = new OnlineUser(request.userToAdd); + channel->addUserLocally(newRemoteUser); + return; + } + } + }); - Command::add("login", [¤tUserKeyPair, ¤tUserName, ¤tUserPassword, &localNodeUsers, &database, &channels](const vector &args) + // Login to account + Command::add("login", [¤tUserKeyPair, ¤tUserName, ¤tUserPassword, &localNodeUsers, &database, &channels, &channelMessageMutex](const vector &args) { if(args.size() != 2) { @@ -131,6 +205,7 @@ int main(int argc, char **argv) } channels.clear(); + lock_guard lock(channelMessageMutex); for(auto localNodeUser : localNodeUsers) { auto nodeStorage = database.getStorage().getStorage(localNodeUser.nodeHash); @@ -149,7 +224,7 @@ int main(int argc, char **argv) if(nodeUserIt.second != localNodeUser.localUser) { User *newRemoteUser = new OnlineUser(nodeUserIt.second); - channel->addUser(newRemoteUser); + channel->addUserLocally(newRemoteUser); } } @@ -173,8 +248,10 @@ int main(int argc, char **argv) } }); - Command::add("register", [¤tUserKeyPair, ¤tUserName, ¤tUserPassword, &localNodeUsers, &database](const vector &args) + // Register account + Command::add("register", [¤tUserKeyPair, ¤tUserName, ¤tUserPassword, &localNodeUsers, &database, &channelMessageMutex](const vector &args) { + lock_guard lock(channelMessageMutex); if(args.size() != 2) { fprintf(stderr, "Expected 2 arguments for command register (username and password), got %u argument(s)\n", args.size()); @@ -206,8 +283,10 @@ int main(int argc, char **argv) currentUserPassword = args[1]; }); - Command::add("cc", [¤tUserKeyPair, ¤tUserName, &database, &channels](const vector &args) + // Create channel + Command::add("cc", [¤tUserKeyPair, ¤tUserName, &database, &channels, &channelMessageMutex](const vector &args) { + lock_guard lock(channelMessageMutex); if(args.size() != 1) { fprintf(stderr, "Expected 1 argument for command cc (channel name), got %u argument(s)\n", args.size()); @@ -232,8 +311,53 @@ int main(int argc, char **argv) Channel::setCurrent(channel); }); - Command::add("jc", [¤tUserKeyPair, &database, &localNodeUsers](const vector &args) + // Add user + Command::add("au", [&offlineChannel, &channelMessageMutex](const vector &args) { + lock_guard 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) + { + 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()); + 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()); + return; + } + + auto userIdRaw = odhtdb::hex2bin(args[0].c_str(), args[0].size()); + odhtdb::Signature::PublicKey userPublicKey(userIdRaw.data(), userIdRaw.size()); + + 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 + { + fprintf(stderr, "Failed to add user to your channel!\n"); + } + }); + + Command::add("jc", [¤tUserKeyPair, &database, &localNodeUsers, &channelMessageMutex](const vector &args) + { + lock_guard lock(channelMessageMutex); if(args.size() != 1) { fprintf(stderr, "Expected 1 argument for command jc (channel join key), got %u argument(s)\n", args.size()); @@ -261,28 +385,15 @@ int main(int argc, char **argv) return; } } -#if 0 - User *newLocalUser = new OnlineUser(localNodeUser.localUser); - odhtdb::DatabaseNode databaseNode(nodeDecryptionKeyResult.second, make_shared(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->addUser(newRemoteUser); - } - } - ChannelSidePanel::addChannel(channel); - channels.push_back(channel); - Channel::setCurrent(channel); - channelAddStoredMessages(channel, nodeStorage); -#endif + database.seed(databaseNode); + // 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 Command::add("scale", [](const vector &args) { if(args.size() != 1) @@ -296,9 +407,31 @@ int main(int argc, char **argv) printf("UI scaling set to %f\n", scaling); }); + // Get username and id (public key) + Command::add("whoami", [¤tUserKeyPair, ¤tUserName](const vector &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()); + }); + sf::Event event; while (window.isOpen()) { + channelMessageMutex.lock(); + Channel *currentChannel = Channel::getCurrent(); + bool waitingToJoin = currentChannel != &offlineChannel && currentChannel->getLocalUser()->type != User::Type::ONLINE; + channelMessageMutex.unlock(); + while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) @@ -316,14 +449,34 @@ int main(int argc, char **argv) sf::View view(viewRect); window.setView(view); } - Channel::getCurrent()->processEvent(event); + else if(event.type == sf::Event::GainedFocus) + window.setFramerateLimit(FRAMERATE_FOCUSED); + else if(event.type == sf::Event::LostFocus) + window.setFramerateLimit(FRAMERATE_NOT_FOCUSED); + currentChannel->processEvent(event); } window.clear(ColorScheme::getBackgroundColor()); ChannelSidePanel::draw(window); - Channel::getCurrent()->draw(window, cache); + currentChannel->draw(window, cache); UsersSidePanel::draw(window); ChannelTopPanel::draw(window); + + if(waitingToJoin) + { + auto windowSize = window.getSize(); + + sf::RectangleShape shadeRect(sf::Vector2f(windowSize.x, windowSize.y)); + shadeRect.setFillColor(sf::Color(0, 0, 0, 200)); + window.draw(shadeRect); + + const sf::Font *FONT = ResourceCache::getFont("fonts/Roboto-Regular.ttf"); + const float FONT_SIZE = 30 * Settings::getScaling(); + sf::Text text("Wait until you are added to the channel", *FONT, FONT_SIZE); + text.setPosition(floor((float)windowSize.x * 0.5f - text.getLocalBounds().width * 0.5f), floor((float)windowSize.y * 0.5f - FONT->getLineSpacing(FONT_SIZE) * 0.5f)); + window.draw(text); + } + //video.draw(window); window.display(); } -- cgit v1.2.3