From c2841e19c227f9c0f7cef3023e012c5c80f6def4 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 3 May 2018 13:16:04 +0200 Subject: Support different types of channel data. Add nickname change command --- src/Channel.cpp | 27 ++++++++++++- src/User.cpp | 3 +- src/main.cpp | 121 ++++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 127 insertions(+), 24 deletions(-) (limited to 'src') 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 #include #include +#include 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(localUser); assert(localOnlineUser->databaseUser->getType() == odhtdb::User::Type::LOCAL); - database->addData(databaseNodeInfo, static_cast(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(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(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(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(); + 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(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 &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 &args) { -- cgit v1.2.3