diff options
m--------- | depends/odhtdb | 0 | ||||
-rw-r--r-- | include/Channel.hpp | 10 | ||||
-rw-r--r-- | include/User.hpp | 1 | ||||
-rw-r--r-- | src/Channel.cpp | 27 | ||||
-rw-r--r-- | src/User.cpp | 3 | ||||
-rw-r--r-- | src/main.cpp | 121 |
6 files changed, 137 insertions, 25 deletions
diff --git a/depends/odhtdb b/depends/odhtdb -Subproject c01f92c1b7f3c257d71961a8dcdf37318aa3f52 +Subproject f3b18e0309ca2dbb997908583f1d44d13d9fc83 diff --git a/include/Channel.hpp b/include/Channel.hpp index 535cce5..17128fd 100644 --- a/include/Channel.hpp +++ b/include/Channel.hpp @@ -4,6 +4,7 @@ #include "Chatbar.hpp" #include "User.hpp" #include "Channel.hpp" +#include "types.hpp" #include <vector> #include <odhtdb/DatabaseNode.hpp> #include <odhtdb/Signature.hpp> @@ -16,6 +17,12 @@ namespace odhtdb namespace dchat { + enum class ChannelDataType : u8 + { + MESSAGE, + NICKNAME_CHANGE + }; + class Channel { public: @@ -30,7 +37,7 @@ namespace dchat const std::string& getName() const; const std::vector<User*> getUsers() const; - User* getUserByPublicKey(const odhtdb::Signature::PublicKey &publicKey); + OnlineUser* getUserByPublicKey(const odhtdb::Signature::PublicKey &publicKey); const odhtdb::DatabaseNode& getNodeInfo() const; // If timestamp is 0, then timestamp is not used @@ -39,6 +46,7 @@ namespace dchat void addUserLocally(User *user); bool addUser(const odhtdb::Signature::PublicKey &userId, const std::string &groupId); void replaceLocalUser(User *newLocalUser); + void changeNick(const std::string &newNick); void processEvent(const sf::Event &event); void draw(sf::RenderWindow &window, Cache &cache); diff --git a/include/User.hpp b/include/User.hpp index e9e334a..821be6f 100644 --- a/include/User.hpp +++ b/include/User.hpp @@ -32,6 +32,7 @@ namespace dchat OnlineUser(const odhtdb::User *databaseUser); virtual const std::string& getName() const override; + std::string name; const odhtdb::User *databaseUser; }; diff --git a/src/Channel.cpp b/src/Channel.cpp index d89a23f..a76a2c6 100644 --- a/src/Channel.cpp +++ b/src/Channel.cpp @@ -3,6 +3,7 @@ #include <odhtdb/Database.hpp> #include <odhtdb/bin2hex.hpp> #include <cstring> +#include <sibs/SafeSerializer.hpp> using namespace std; @@ -93,7 +94,7 @@ namespace dchat return users; } - User* Channel::getUserByPublicKey(const odhtdb::Signature::PublicKey &publicKey) + OnlineUser* Channel::getUserByPublicKey(const odhtdb::Signature::PublicKey &publicKey) { auto userIt = publicKeyOnlineUsersMap.find(publicKey); if(userIt != publicKeyOnlineUsersMap.end()) @@ -118,7 +119,12 @@ namespace dchat { auto localOnlineUser = static_cast<OnlineUser*>(localUser); assert(localOnlineUser->databaseUser->getType() == odhtdb::User::Type::LOCAL); - database->addData(databaseNodeInfo, static_cast<const odhtdb::LocalUser*>(localOnlineUser->databaseUser), odhtdb::DataView((void*)msg.data(), msg.size())); + + sibs::SafeSerializer serializer; + serializer.add(ChannelDataType::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(); } else @@ -178,6 +184,23 @@ namespace dchat addUserLocally(newLocalUser); } + void Channel::changeNick(const std::string &newNick) + { + if(database && localUser->type == User::Type::ONLINE) + { + auto localOnlineUser = static_cast<OnlineUser*>(localUser); + assert(localOnlineUser->databaseUser->getType() == odhtdb::User::Type::LOCAL); + + 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(); + } + } + void Channel::processEvent(const sf::Event &event) { chatbar.processEvent(event, this); diff --git a/src/User.cpp b/src/User.cpp index 2908fd4..16b3648 100644 --- a/src/User.cpp +++ b/src/User.cpp @@ -14,6 +14,7 @@ namespace dchat OnlineUser::OnlineUser(const odhtdb::User *_databaseUser) : User(Type::ONLINE), + name("randomUser69"), databaseUser(_databaseUser) { assert(databaseUser); @@ -21,7 +22,7 @@ namespace dchat const std::string& OnlineUser::getName() const { - return databaseUser->getName(); + return name; } OfflineUser::OfflineUser(const std::string &_name) : diff --git a/src/main.cpp b/src/main.cpp index 59b89a5..3804f6f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -56,17 +56,67 @@ odhtdb::DatabaseNode createDatabaseNodeFromJoinKey(const string &joinKey) return odhtdb::DatabaseNode(encryptionKey, nodeHash); } -void channelAddStoredMessage(Channel *channel, odhtdb::DatabaseStorageObject *nodeStorageObject) +void channelChangeUserNickname(Channel *channel, const StringView data, const odhtdb::Signature::PublicKey &userPublicKey) { - User *user = channel->getUserByPublicKey(nodeStorageObject->creatorPublicKey); + auto user = channel->getUserByPublicKey(userPublicKey); if(!user) { - fprintf(stderr, "Missing user? %s\n", nodeStorageObject->creatorPublicKey.toString().c_str()); + fprintf(stderr, "Nickname change: user with public key %s not found in channel %s\n", userPublicKey.toString().c_str(), channel->getName().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); + sibs::SafeDeserializer deserializer((const u8*)data.data, data.size); + u8 nameLength = deserializer.extract<u8>(); + if(nameLength > 0) + { + user->name.resize(nameLength); + deserializer.extract((u8*)&user->name[0], nameLength); + } + // We dont care if there is more data to read (malicious packet), we already got all the data we need +} + +void channelAddStoredMessage(Channel *channel, const odhtdb::Signature::PublicKey &creatorPublicKey, const StringView decryptedObject, u64 timestamp) +{ + User *user = channel->getUserByPublicKey(creatorPublicKey); + if(!user) + { + fprintf(stderr, "Missing user? %s\n", creatorPublicKey.toString().c_str()); + return; + } + + if(decryptedObject.size > 1) + { + auto channelDataType = (ChannelDataType)static_cast<const char*>(decryptedObject.data)[0]; + StringView decryptedData((const char*)decryptedObject.data + 1, decryptedObject.size - 1); + switch(channelDataType) + { + case ChannelDataType::MESSAGE: + { + string msg(decryptedData.data, decryptedData.size); + channel->addLocalMessage(msg, user, ntp::NtpTimestamp::fromCombined(timestamp).seconds); + break; + } + case ChannelDataType::NICKNAME_CHANGE: + { + try + { + channelChangeUserNickname(channel, decryptedData, creatorPublicKey); + } + catch(sibs::DeserializeException &e) + { + fprintf(stderr, "Failed to deserialize nick change\n"); + } + break; + } + default: + fprintf(stderr, "Got unexpected channel data type: %u\n", channelDataType); + break; + } + } + else + { + fprintf(stderr, "ADD_DATA packet too small, ignoring...\n"); + } } void channelAddStoredMessages(Channel *channel, const odhtdb::DatabaseStorageObjectList *nodeStorage) @@ -76,7 +126,8 @@ void channelAddStoredMessages(Channel *channel, const odhtdb::DatabaseStorageObj { if(nodeStorageAddedObject->decryptedObject.operation == odhtdb::DatabaseOperation::ADD_DATA) { - channelAddStoredMessage(channel, nodeStorageAddedObject); + StringView decryptedObject((const char*)nodeStorageAddedObject->decryptedObject.data.data, nodeStorageAddedObject->decryptedObject.data.size); + channelAddStoredMessage(channel, nodeStorageAddedObject->creatorPublicKey, decryptedObject, nodeStorageAddedObject->createdTimestamp); } } } @@ -149,15 +200,7 @@ int main(int argc, char **argv) { if(*request.nodeHash == *channel->getNodeInfo().getRequestHash()) { - 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); + channelAddStoredMessage(channel, request.creatorUser->getPublicKey(), StringView((const char*)request.decryptedData.data, request.decryptedData.size), request.timestamp); return; } } @@ -427,9 +470,9 @@ int main(int argc, char **argv) { if(args.size() != 2) { - string errMsg = "Expected 2 arguments for command addbind, got %u argument("; + string errMsg = "Expected 2 arguments for command addbind, got "; errMsg += to_string(args.size()); - errMsg += ")"; + errMsg += " argument(s)"; Channel::getCurrent()->addLocalMessage(errMsg, Channel::getCurrent()->getSystemUser()); return; } @@ -456,9 +499,9 @@ int main(int argc, char **argv) { if(args.size() != 1) { - string errMsg = "Expected 1 argument for command removebind, got %u argument("; + string errMsg = "Expected 1 argument for command removebind, got "; errMsg += to_string(args.size()); - errMsg += ")"; + errMsg += " argument(s)"; Channel::getCurrent()->addLocalMessage(errMsg, Channel::getCurrent()->getSystemUser()); return; } @@ -485,9 +528,9 @@ int main(int argc, char **argv) { if(args.size() != 0) { - string errMsg = "Expected 0 arguments for command removebind, got %u argument("; + string errMsg = "Expected 0 arguments for command removebind, got "; errMsg += to_string(args.size()); - errMsg += ")"; + errMsg += " argument(s)"; Channel::getCurrent()->addLocalMessage(errMsg, Channel::getCurrent()->getSystemUser()); return; } @@ -521,6 +564,42 @@ int main(int argc, char **argv) Channel::getCurrent()->addLocalMessage(response, Channel::getCurrent()->getSystemUser()); }); + // Change nick of current user in current channel + Command::add("nick", [¤tUserKeyPair, &offlineChannel](const vector<string> &args) + { + if(args.size() != 1) + { + string errMsg = "Expected 1 argument for command nick, got "; + errMsg += to_string(args.size()); + errMsg += " argument(s)"; + Channel::getCurrent()->addLocalMessage(errMsg, Channel::getCurrent()->getSystemUser()); + return; + } + + if(!currentUserKeyPair) + { + Channel::getCurrent()->addLocalMessage("You need to be logged in to change your nickname", Channel::getCurrent()->getSystemUser()); + return; + } + + if(Channel::getCurrent() == &offlineChannel) + { + Channel::getCurrent()->addLocalMessage("You need to be in a channel to change your nickname", Channel::getCurrent()->getSystemUser()); + return; + } + + if(args[0].size() == 0 || args[0].size() > 255) + { + Channel::getCurrent()->addLocalMessage("Invalid nickname. Nickname has to be between 1 and 255 characters", Channel::getCurrent()->getSystemUser()); + return; + } + + Channel::getCurrent()->changeNick(args[0]); + string msg = "Your nickname was changed to "; + msg += args[0]; + Channel::getCurrent()->addLocalMessage(msg, Channel::getCurrent()->getSystemUser()); + }); + // Get channel join key Command::add("joinkey", [¤tUserKeyPair, ¤tUserName, &offlineChannel](const vector<string> &args) { |